// QPART change here

/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
 *
 * Copyright (c) 1997 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the Computer Systems
 *	Engineering Group at Lawrence Berkeley Laboratory.
 * 4. Neither the name of the University nor of the Laboratory may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $Header: /cvsroot/nsnam/ns-2/mac/mac-802_11.cc,v 1.56 2008/03/28 04:43:06 tom_henderson Exp $
 *
 * Ported from CMU/Monarch's code, nov'98 -Padma.
 * Contributions by:
 *   - Mike Holland
 *   - Sushmita
 */

#include "delay.h"
#include "connector.h"
#include "packet.h"
#include "random.h"
#include "mobilenode.h"

// #define DEBUG 99

#include "arp.h"
#include "ll.h"
#include "mac.h"
#include "mac-timers.h"
#include "mac-802_11.h"
#include "cmu-trace.h"

// 1. QPART
#include <math.h>
#include "ip.h"
#include "scheduler.h"
#include "../aodv/aodv.h"
#include "../aodv/aodv_packet.h"
#include "liste_cw.h"
// end 1

// Added by Sushmita to support event tracing
#include "agent.h"
#include "basetrace.h"

// 2. QPART
#define INTERVAL 1 //+ 0.01*Random::uniform()  //frequence pr le calcul de l'utilisation du canal chaque seconde plus qqe gigue pr ne pas calculer pr ts les noeud en meme tps
#define IntervalCW 0.1 		// frequence de mise a jour de la taille de la fenetre de contention
#define IntervalPrio 0.1	// f equence de mise a jour de la priorite du flux
#define beta 1			//constante pour le calcul de la taille de la CW pour les trafic TR
#define q 5			//seuil du nombre de paquet dans la file
#define gama 0.1 		//constante pour le calcul de la taille de la CW pour les trafic BE
#define f 0.001			//seuil de congestion pr le temps innocup� du canal en ms
#define CURRENT_TIME Scheduler::instance().clock()
#define teta 0.000002		//la difference entre les seuils d'admissions entre deux flux de priorit� cons�cutive = 2micro-seconde = 0.002 milli seconde
#define nu 0.0001		//le plus petit seuil d'admission = 0.1 milli-seconde
#define delta 0.002		//2 milli seconde
#define Pmax 250		//la valeur max de priorit� que peut prendre un flux
//#define int_difer 0.000001
/* ======================================================================
 Global Variables
 ====================================================================== */
Packet *p;
Band *bande = (Band *)malloc(sizeof(Band));
lcw *listcw = (lcw *)malloc(sizeof(lcw));
// end 2

/* our backoff timer doesn't count down in idle times during a
 * frame-exchange sequence as the mac tx state isn't idle; genreally
 * these idle times are less than DIFS and won't contribute to
 * counting down the backoff period, but this could be a real
 * problem if the frame exchange ends up in a timeout! in that case,
 * i.e. if a timeout happens we've not been counting down for the
 * duration of the timeout, and in fact begin counting down only
 * DIFS after the timeout!! we lose the timeout interval - which
 * will is not the REAL case! also, the backoff timer could be NULL
 * and we could have a pending transmission which we could have
 * sent! one could argue this is an implementation artifact which
 * doesn't violate the spec.. and the timeout interval is expected
 * to be less than DIFS .. which means its not a lot of time we
 * lose.. anyway if everyone hears everyone the only reason a ack will
 * be delayed will be due to a collision => the medium won't really be
 * idle for a DIFS for this to really matter!!
 */

inline void Mac802_11::checkBackoffTimer() {
	if (is_idle() && mhBackoff_.paused())
		mhBackoff_.resume(phymib_.getDIFS());
	if (!is_idle() && mhBackoff_.busy() && !mhBackoff_.paused())
		mhBackoff_.pause();
}

// 3. QPART
/*------------------------------------BILEL--------------------------------------------------------
 cette fonction permet de retourner un float al�atoire
 entre deux valeurs pass�es en param�tres
 --------------------------------------------------------------------------------------------------*/
float myRandom(float m, float n) {
	float t=0;
	t=Random::uniform();
	return (t*(n - m) + m);
}
/*---------------------------------/Bilel---------------------------------------------------------*/

/*---------------------------------------BILEL-----------------------------------------------------
 cette fonction permet de retourner un float representant un temps aleatoire
 avant de d�cider le rejet ou non du flux consid�r�
 --------------------------------------------------------------------------------------------------*/
double defer_time(Packet *p) {
	struct hdr_cmn *ch = HDR_CMN(p);
	struct hdr_ip *ih = HDR_IP(p);
	double t1=0;
	double t2=0;
	double rand=0;
	//float mnt=0;			//valeur aleatoire entre t1 et t2;
	t1 = (ih->prio_) * delta;
	t2 = (ih->prio_ + 1) * delta;
	rand = myRandom(t1, t2);
	// 2. M changed
	//float som = deb+rand;
	// end 2
	return (rand);

}
/*---------------------------------/Bilel---------------------------------------------------------*/
char *Packet_type(Packet *p) {
	struct hdr_mac802_11 *mh = HDR_MAC802_11(p);
	switch (mh->dh_fc.fc_type) {
	case MAC_Type_Control:
		switch (mh->dh_fc.fc_subtype) {
		case MAC_Subtype_RTS:
			return "RTS";
			break;
			/*case MAC_Subtype_FN:
			 return "FN";
			 break;*/
		case MAC_Subtype_CTS:
			return "CTS";
			break;
		case MAC_Subtype_ACK:
			return "ACK";
			break;
		default:
			return "DATA";
		}
	default:
		return "DATA";
	}
}

/*---------------------------------------BILEL-----------------------------------------------------
 cette fonction permet de retourner un float representant
 le nouveau idle time sur le canal
 --------------------------------------------------------------------------------------------------*/
float Mac802_11::recalcul_idle(MacState newState, Packet *p) {
	float tps_occup=0;
	float new_idle=0;
	//MacState stateNow;
	//stateNow = newState;
	if ((newState == MAC_SEND) || (newState == MAC_RECV)) {
		tps_occup=txtime(p)+txtime(phymib_.getACKlen(), basicRate_);
		//printf("---------------data\n");
	}

	if (newState == MAC_ACK) {
		tps_occup=txtime(phymib_.getACKlen(), basicRate_);
		//printf("---------------ack\n");
	}
	if (newState == MAC_RTS) {
		tps_occup=txtime(phymib_.getRTSlen(), basicRate_);
		//printf("---------------rts\n");
	}
	if (newState == MAC_CTS) {
		tps_occup=txtime(phymib_.getCTSlen(), basicRate_);
		//printf("---------------cts\n");
	}
	New_somme_tx = New_somme_tx + tps_occup;
	new_idle = 1 - tps_occup;//INTERVAL;
	return new_idle;
}
/*-------------------------------------------------------------------------------------------------
 on fait des modifications dans la fonction Mac802_11::transmit de sorte que :
 1. avant de passer le pkt vers la couche physique on fait la mise � jour de la priorit�.
 2. calculer le seuil d'admission en fonction de la priorit� et affecter cette valeur dans le nouveau champs 	cr�e au niveau de l'entete IP.
 3. v�rification SI le idle time (ch->Fn_) est sup�rieur au seuil d'admission (ih->seuil_)
 ALORS transmettre
 SINON attendre un laps de temps al�atoire calcul� par la fonction defer_time
 puis calculer le nouveau idle time
 v�rification SI le nouveau idle time > ih->seuil_ ALORS transmettre
 SINON dropper le paquet.

 -------------------------------------------------------------------------------------------------*/
// end 3

inline void Mac802_11::transmit(Packet *p, double timeout) {
	// 4. QPART
	struct hdr_cmn *ch = HDR_CMN(p);
	struct hdr_ip *ih = HDR_IP(p);
	//struct hdr_mac802_11 *mh = HDR_MAC802_11(p);
	// end 4
	tx_active_ = 1;

	if (EOTtarget_) {
		assert (eotPacket_ == NULL);
		eotPacket_ = p->copy();
	}

	/*
	 * If I'm transmitting without doing CS, such as when
	 * sending an ACK, any incoming packet will be "missed"
	 * and hence, must be discarded.
	 */
	if (rx_state_ != MAC_IDLE) {
		//assert(dh->dh_fc.fc_type == MAC_Type_Control);
		//assert(dh->dh_fc.fc_subtype == MAC_Subtype_ACK);
		assert(pktRx_);
		struct hdr_cmn *ch = HDR_CMN(pktRx_);
		ch->error() = 1; /* force packet discard */
	}

	/*
	 * pass the packet on the "interface" which will in turn
	 * place the packet on the channel.
	 *
	 * NOTE: a handler is passed along so that the Network
	 *       Interface can distinguish between incoming and
	 *       outgoing packets.
	 */

	// 5. QPART
	//1. BILEL-----------------------------------------------Mise a jour de la priorit� des pkt avant l envoi
	if (ih->fid_ != 0) //le fid == 0 A VERIFIER il est r�server pour les pkt de controle
	{
		double dif;
		dif = CURRENT_TIME - ch->date;
		int prio_temp = 0;
		prio_temp = (int) ih->prio_ + (dif/0.1);
		if (prio_temp < Pmax) {
			ih->prio_ = prio_temp;
		} else {
			ih->prio_ = Pmax;
		}
	}
	//BILEL-------------------------------------------------FIN de mise a jour des priorit�s des pkts


	//2. BILEL----------------------------------------------------------------Calcul du seuil d admission
	double Tk=0.0001;
	int Pk=0; //le seuil le plus ptit
	Pk = ih->prio_;
	Tk = (Pmax - Pk) * teta + nu; //formule du seuil d admission (teta et nu constantes)
	ih->seuil_ = Tk;
	//BILEL-------------------------------------------------------------FIN calcul du seuil d admission


	//3. BILEL------------------------------------------------------------------Controle d'admission
	double deferTime=0;
	//float taw=0;
	//mhDefer2_.start(0.03);
	/*if (ih->fid_ == 0)		//s'assurer que le pkt n est pas un pkt de controle
	 {
	 //printf("c'est un pkt de control\n");
	 //printf("avec fid = %d  et uid = %d\n", ih->fid_, ch->uid_);
	 downtarget_->recv(p->copy(), this);
	 }*/
	//else {
	//pkt de donn�e
	if (ih->fid_ != 0) // DATA
	{
		//if (ch->uid_ != 0)
		//{
		//printf("le seuil avant de transmettre est      (fid=%d) (uid%d)         %f\n",ih->fid_, ch->uid_, ih->seuil_);
		//printf("le idle time avant de transmettre est  (fid=%d) (uid%d)         %f\n\n",ih->fid_, ch->uid_, ch->Fn_);

		if (ch->Fn_ < ih->seuil_) //le idle inferieur au seuil :
		{

			//printf("**********************************************************\n");
			//printf("             il faut attendre un defer time\n");
			//printf("la valeur du seuil est             = %f\n", ih->seuil_);
			//printf("la valeur du idle est              = %f\n", ch->Fn_);
			deferTime = defer_time(p); //1. attendre defer time
			//printf("la valeur du defer est             = %f\n", deferTime);


			/*if (deferTime < 0.0047)
			 {
			 mhDefer2_.start(deferTime);
			 } else {
			 mhDefer2_.start(0.0047);
			 }
			 */

			//mhDefer2_.start(deferTime);

			float n_idle=0;
			n_idle = recalcul_idle(tx_state_, p);
			//printf("la NOUVELLE valeur du idle est     = %f\n", n_idle);
			if (n_idle < ih->seuil_) //la valeur de new idle est tjrs < au seuil_
			{
				ch->error() = 1;
				//drop(p);
				//return;
				//drop(p);
			} else {
				//printf("Apres defer time le idle augmente : Donc j'accepte sans probleme\n");
			}

		} else {
			//downtarget_->recv(p->copy(), this);
			//printf("OK ! ! ! j accepte DIRECTEMENT \n");
		}
	}

	//BILEL------------------------------------------------------------------FIN Controle d'admission
	//}
	// end 5

	downtarget_->recv(p->copy(), this);
	mhSend_.start(timeout);
	mhIF_.start(txtime(p));
}

// 6. QPART
/*inline void
 Mac802_11::setRxState(MacState newState)
 {
 rx_state_ = newState;
 checkBackoffTimer();
 }

 inline void
 Mac802_11::setTxState(MacState newState)
 {
 tx_state_ = newState;
 checkBackoffTimer();
 }*/
//***********************************************fct qui ns retourne le type du pckt

//-------------------------------------------------------------------------------------

int is_qos(Packet *p) {
	//struct hdr_mac802_11 *mh = HDR_MAC802_11(p);
	struct hdr_ip *ih = HDR_IP(p);
	switch (ih->fid_) {
	//case 1 : return 1;
	case 1:
		return 0;
	case 2:
		return 0;
	case 3:
		return 0;
	case 4:
		return 0;
	case 5:
		return 0;
	case 6:
		return 0;
	case 7:
		return 0;
	case 8:
		return 0;
	case 9:
		return 0;
	case 10:
		return 0;
	default:
		return 1;
	}
}

//------------------------------------------------------------------------------------fcts ajout�es
inline void Mac802_11::setRxState(MacState newState, Packet *p) {

	//struct hdr_ip *ih = HDR_IP(p);
	double interval;
	//  char *type;
	rx_state_ = newState;
	checkBackoffTimer();
	//*************************************************************************


	if (rx_state_ == MAC_RECV) {
		//interval=txtime(p);
		//ou bien on calcul la durre de l'ack avec le data
		interval=txtime(p);//+txtime(phymib_.getACKlen(),basicRate_);
	}
	if (rx_state_ == MAC_ACK) {
		interval=txtime(phymib_.getACKlen(), basicRate_);
	}
	if (rx_state_ == MAC_RTS) {
		interval=txtime(phymib_.getRTSlen(), basicRate_);
	}
	if (rx_state_ == MAC_CTS) {
		interval=txtime(phymib_.getCTSlen(), basicRate_);
	}

	if (interval < 0)
		interval =0;
	if (interval > INTERVAL)
		interval = 0;
	somme_rx=somme_rx+interval;

}

inline void Mac802_11::setTxState(MacState newState, Packet *p) {

	double interval;
	//  char *type;
	tx_state_ = newState;
	//double somme_rx;

	checkBackoffTimer();
	//**************************************************************

	if (tx_state_ == MAC_SEND) {
		//interval=txtime(p);
		//ou bien on calcul la durre de l'ack avec le data
		interval=txtime(p);//+txtime(phymib_.getACKlen(),basicRate_);
	}

	if (tx_state_ == MAC_ACK) {
		interval=txtime(phymib_.getACKlen(), basicRate_);
	}
	if (tx_state_ == MAC_RTS) {
		interval=txtime(phymib_.getRTSlen(), basicRate_);

	}
	if (tx_state_ == MAC_CTS) {
		interval=txtime(phymib_.getCTSlen(), basicRate_);

	}

	if (interval < 0)
		interval =0;
	if (interval > INTERVAL)
		interval = 0;
	somme_tx=somme_tx+interval;

}
//**************************---------------------------------++++++++++++++++++++++++++++++++++++++++
// end 6

// 2.33 khong co
//#ifdef MIKE // need to add rst_cw etc.
// inline void
// Mac802_11::postBackoff(int pri)
//  {
//	 // 7. QPART
//       if (is_qos(p)){
//       rst_cwQos(pri);
//       }
//       else
//        {
//	rst_cwBe(pri);
//	}
//       assert(!mhBackoff_.busy(pri));
//if (is_qos(p)){
//	//12.12
//	cwQos_ = findCW(listcw, ih->fid_);
//        mhBackoff_.start(pri, cwQos_[pri], CWOffset_[pri], true);
//       } else {
//	mhBackoff_.start(pri, cwBe_[pri], CWOffset_[pri], true);
//       }
//// end 7
// }
// #endif
//
//
// /*
//  * This macro is only used in one place, and should be removed.
//  */
//
// #define CFP_BEACON(__p) (                                                                       \
//         (((struct beacon_frame *)HDR_MAC802_11(__p))->bf_fc.fc_type == MAC_Type_Management)     \
//         &&                                                                                      \
//         (((struct beacon_frame *)HDR_MAC802_11(__p))->bf_fc.fc_subtype == MAC_Subtype_Beacon)   \
// )
//
//// Mike change ends
// end 2.33 khong co

/* ======================================================================
 TCL Hooks for the simulator
 ====================================================================== */
static class Mac802_11Class : public TclClass {
public:
	Mac802_11Class() :
		TclClass("Mac/802_11") {
	}
	TclObject* create(int, const char*const*) {
		return (new Mac802_11());

	}
} class_mac802_11;

/* ======================================================================
 Mac  and Phy MIB Class Functions
 ====================================================================== */

PHY_MIB::PHY_MIB(Mac802_11 *parent) {
	/*
	 * Bind the phy mib objects.  Note that these will be bound
	 * to Mac/802_11 variables
	 */

	parent->bind("CWMin_", &CWMin);
	parent->bind("CWMax_", &CWMax);
	parent->bind("SlotTime_", &SlotTime);
	parent->bind("SIFS_", &SIFSTime);
	parent->bind("BeaconInterval_", &BeaconInterval);

	parent->bind("PreambleLength_", &PreambleLength);
	parent->bind("PLCPHeaderLength_", &PLCPHeaderLength);
	parent->bind_bw("PLCPDataRate_", &PLCPDataRate);
}

MAC_MIB::MAC_MIB(Mac802_11 *parent) {
	/*
	 * Bind the phy mib objects.  Note that these will be bound
	 * to Mac/802_11 variables
	 */

	parent->bind("RTSThreshold_", &RTSThreshold);
	parent->bind("ShortRetryLimit_", &ShortRetryLimit);
	parent->bind("LongRetryLimit_", &LongRetryLimit);
	parent->bind("ScanType_", &ScanType);
	parent->bind("ProbeDelay_", &ProbeDelay);
	parent->bind("MaxChannelTime_", &MaxChannelTime);
	parent->bind("MinChannelTime_", &MinChannelTime);
	parent->bind("ChannelTime_", &ChannelTime);
}

/* ======================================================================
 Mac Class Functions
 ====================================================================== */
// 8. QPART
//Mac802_11::Mac802_11(PHY_MIB *p, MAC_MIB *m) : Mac(), mhIF_(this), mhNav_(this), mhRecv_(this), mhSend_(this), mhDefer_(this, p->SlotTime), mhBackoff_(this, p->SlotTime)        //****** mhPrio_(this),
Mac802_11::Mac802_11() :
	Mac(), phymib_(this), macmib_(this), mhIF_(this), mhNav_(this),
			mhBandwith_(this), mhCW_(this), mhRecv_(this), mhSend_(this),
			mhDefer_(this), mhDefer2_(this), mhBackoff_(this), mhBeacon_(this),
			mhProbe_(this)
/*Mac802_11::Mac802_11() : 
 Mac(), phymib_(this), macmib_(this), mhIF_(this), mhNav_(this), 
 mhRecv_(this), mhSend_(this), 
 mhDefer_(this), mhBackoff_(this), mhBeacon_(this), mhProbe_(this)*/
// end 8
{
	// 9. QPART
	//float int_difer=0;
	//int prior;
	cwQos_prec= 31;
	cwBe_prec = 31;
	utilisation=0;
	nbre_pkt=0;
	Qn=0;
	pr=0;
	Fn=0;
	somme_rx=0;
	somme_tx=0;
	New_somme_tx=0;

	//ch->Fn = Fn;
	mhBandwith_.start(INTERVAL);//----------------------
	// end 9

	nav_ = 0.0;
	tx_state_ = rx_state_ = MAC_IDLE;
	tx_active_ = 0;

	// 10. QPART
	//----------------------------------------------------------------------
	// declaration des var pour Cw
	mhCW_.start(IntervalCW);

	// declaration des variable pour Prio
	//mhPrio_.start(IntervalPrio);
	//----------------------------------------------------------------------
	// end 10

	eotPacket_ = NULL;
	pktRTS_ = 0;
	pktCTRL_ = 0;
	pktBEACON_ = 0;
	pktASSOCREP_ = 0;
	pktASSOCREQ_ = 0;
	pktAUTHENTICATE_ = 0;
	pktPROBEREQ_ = 0;
	pktPROBEREP_ = 0;
	BeaconTxtime_ = 0;
	infra_mode_ = 0;
	cw_ = phymib_.getCWMin();

	// 11. QPART
	cwBe_ = phymib_.getCWMin();
	cwQos_ = phymib_.getCWMin();
	// end 11

	ssrc_ = slrc_ = 0;
	// Added by Sushmita
	et_ = new EventTrace();

	sta_seqno_ = 1;
	cache_ = 0;
	cache_node_count_ = 0;
	client_list = NULL;
	ap_list = NULL;
	Pr = 0;
	ap_temp = -1;
	head = 0;
	ap_addr = -1;
	associated = 0;
	authenticated = 0;
	OnMinChannelTime = 0;
	OnMaxChannelTime = 0;
	Recv_Busy_ = 0;
	handoff= 0;
	//	ssid_ = "0";
	memset(priority_queue, 0, sizeof(priority_queue));

	// chk if basic/data rates are set
	// otherwise use bandwidth_ as default;

	Tcl& tcl = Tcl::instance();
	tcl.evalf("Mac/802_11 set basicRate_");
	if (strcmp(tcl.result(), "0") != 0)
		bind_bw("basicRate_", &basicRate_);
	else
		basicRate_ = bandwidth_;

	tcl.evalf("Mac/802_11 set dataRate_");
	if (strcmp(tcl.result(), "0") != 0)
		bind_bw("dataRate_", &dataRate_);
	else
		dataRate_ = bandwidth_;

	bind_bool("bugFix_timer_", &bugFix_timer_);

	EOTtarget_ = 0;
	bss_id_ = IBSS_ID;
}

int Mac802_11::command(int argc, const char*const* argv) {
	if (argc == 3) {
		if (strcmp(argv[1], "eot-target") == 0) {
			EOTtarget_ = (NsObject*) TclObject::lookup(argv[2]);
			if (EOTtarget_ == 0)
				return TCL_ERROR;
			return TCL_OK;
		}
		if (strcmp(argv[1], "ap") == 0) {
			ap_addr = addr();
			bss_id_ = addr();
			infra_mode_ = 1;
			mhBeacon_.start((Random::random() % cw_) * phymib_.getSlotTime());
			return TCL_OK;
		}
		if (strcmp(argv[1], "ScanType") == 0) {
			if (strcmp(argv[2], "ACTIVE") == 0) {
				ScanType_ = ACTIVE;
				infra_mode_ = 1;
				ap_list = NULL;
				mhProbe_.start(macmib_.getProbeDelay());
			} else if (strcmp(argv[2], "PASSIVE") == 0) {
				ScanType_ = PASSIVE;
				mhProbe_.start(macmib_.getChannelTime());
				infra_mode_ = 1;
			}
			return TCL_OK;
		} else if (strcmp(argv[1], "log-target") == 0) {
			logtarget_ = (NsObject*) TclObject::lookup(argv[2]);
			if (logtarget_ == 0)
				return TCL_ERROR;
			return TCL_OK;
		} else if (strcmp(argv[1], "nodes") == 0) {
			if (cache_)
				return TCL_ERROR;
			cache_node_count_ = atoi(argv[2]);
			cache_ = new Host[cache_node_count_ + 1];
			assert(cache_);
			bzero(cache_, sizeof(Host) * (cache_node_count_+1 ));
			return TCL_OK;
		} else if (strcmp(argv[1], "eventtrace") == 0) {
			// command added to support event tracing by Sushmita
			et_ = (EventTrace *)TclObject::lookup(argv[2]);
			return (TCL_OK);
		}
	}
	return Mac::command(argc, argv);
}

// 12. QPART
void afficheband(Band *p) {
	while (p) {
		printf("Src = %d  Dst =  Fn =%f\n", p->src, p->Fn); // p->dst,
		p=p->next;
		printf("********\n");
	}
}

//**************************************************************************************************
//-----------------------fct determinant le type de flux
//retourne 1 si flux Temps r�el et 0 si flux Best Effort
//**************************************************************************************************


void Mac802_11::bandwithHandler() {
	//struct hdr_cmn *ch = HDR_CMN(p);
	//float inter;
	utilisation = (somme_rx + somme_tx)/INTERVAL;
	//float Fn=0;
	if (utilisation <= 1) {
		Fn = 1 - utilisation;
	} else {
		Fn = 0;
	}
	somme_rx = 0;
	somme_tx = 0;
	//inter = calcul_idle();
	//  ch->Fn_ = Fn;
	//afficheband(bande);
	//printf("node = %d ------ idle time =  %f -----  \n",index_, Fn);
	//printf("\nNode = %d ---- utilisation = %f ---- idle time =  %f\n\n",index_ ,utilisation, Fn); //affichage de l'occupation pour chaque noeud chaque seconde


	//sendFn(2);
	mhBandwith_.start(INTERVAL);

}
//12-12
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

bool lookupfid(lcw *l, int fid) {
	lcw *pcour = (lcw *)malloc(sizeof(lcw));
	pcour = l;

	if (pcour==NULL) {
		return false;
	}

	while (pcour) {
		if (pcour->fid == fid) {
			return true;
		}
		pcour=pcour->next;
	}
	return false;
}

int findCW(lcw *l, int fid) {
	lcw *pcour = (lcw *)malloc(sizeof(lcw));
	//if(!pcour) return;	//Si l'allocation a �chou�e
	*pcour = *l;
	while (pcour != NULL) {
		if (pcour->fid == fid) {
			return (pcour->CW);
		}
		pcour=pcour->next; //EN PRINCIPE AVEC*
	}
	//return false;
	//      }
}

void insertcw(lcw **l, int fid, int cw) //ns_addr_t src, ns_addr_t dst
{
	lcw *pcour = (lcw *)malloc(sizeof(lcw));
	//if(!pcour) return;	//Si l'allocation a �chou�e
	pcour = *l;
	if (lookupfid(*l, fid)) { //si le fid  existe  deja alorscalcul_seuil
		while (pcour->fid != fid) {
			pcour = pcour->next;
		}
		pcour->CW = cw;
	} else //si le fid existe il suffit de mettre a jour sa periorit�
	{
		//printf("fid n existe pas!!! je le cree\n");
		while (pcour->next != NULL) {
			pcour = pcour->next;
		}
		lcw *e = (lcw *)malloc(sizeof(lcw));
		//if(!e) return;	//Si l'allocation a �chou�e
		e->fid=fid;
		e->CW=cw;
		//e->src=src;
		//e->dst=dst;
		e->next=NULL;
		pcour->next = e;
	}
}

void affichecw(lcw *l) {
	lcw *pcour = (lcw *)malloc(sizeof(lcw));
	*pcour = *l;
	while (pcour) {
		if (pcour->fid != 0) {
			printf("LISTE CW      fid  == %d  cw == %d\n", pcour->fid,
					pcour->CW);

			//printf("");
			//p=p->next;
			printf("********\n");
		}
		pcour=pcour->next;
	}
	printf("*****************************\n\n");
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//12-12

//**************************************************************************************************
//-----------------------fct determinant le type de flux
//retourne 1 si flux Temps r�el et 0 si flux Best Effort
//**************************************************************************************************

//-------------------------------------------------------------------------------------------------
//---------------------------------adaptation de la taille de la CW---------------------------------------------
void Mac802_11::CWHandler() {

	//cwQos_prec = cwQos_ ;
	cwQos_ = cwQos_prec + beta * (q - Qn);//formuel qos

	if (cwQos_ <= 5) {
		cwQos_ = 31;//phymib_.getCWMin();
		//le pkt doit etre envoyer mnt

	}

	cwBe_prec = cwBe_;
	cwBe_ = cwBe_prec * (1 + gama * (f - Fn)); //formuel Be

	if (cwBe_prec <= 5) {
		cwBe_ = 31;//phymib_.getCWMin();
		//le pkt doit etre envoyer mnt
	}

	mhCW_.start(IntervalCW);
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// end 12

// Added by Sushmita to support event tracing
void Mac802_11::trace_event(char *eventtype, Packet *p) {
	if (et_ == NULL)
		return;
	char *wrk = et_->buffer();
	char *nwrk = et_->nbuffer();
	//char *src_nodeaddr =
	//       Address::instance().print_nodeaddr(iph->saddr());
	//char *dst_nodeaddr =
	//      Address::instance().print_nodeaddr(iph->daddr());

	struct hdr_mac802_11* dh = HDR_MAC802_11(p);

	//struct hdr_cmn *ch = HDR_CMN(p);

	if (wrk != 0) {
		sprintf(wrk, "E -t "TIME_FORMAT" %s %2x ",
				et_->round(Scheduler::instance().clock()),
				eventtype,
				//ETHER_ADDR(dh->dh_sa)
				ETHER_ADDR(dh->dh_ta)
		);
	}
	if (nwrk != 0) {
		sprintf(nwrk, "E -t "TIME_FORMAT" %s %2x ",
				et_->round(Scheduler::instance().clock()),
				eventtype,
				//ETHER_ADDR(dh->dh_sa)
				ETHER_ADDR(dh->dh_ta)
		);
	}
	et_->dump();
}

/* ======================================================================
 Debugging Routines
 ====================================================================== */
void Mac802_11::trace_pkt(Packet *p) {
	struct hdr_cmn *ch = HDR_CMN(p);
	struct hdr_mac802_11* dh = HDR_MAC802_11(p);
	u_int16_t *t = (u_int16_t*) &dh->dh_fc;

	fprintf(stderr, "\t[ %2x %2x %2x %2x ] %x %s %d\n", *t, dh->dh_duration, 
	ETHER_ADDR(dh->dh_ra), ETHER_ADDR(dh->dh_ta), index_, packet_info.name(ch->ptype()), ch->size());
}

void Mac802_11::dump(char *fname) {
	fprintf(stderr, "\n%s --- (INDEX: %d, time: %2.9f)\n", fname, index_,
			Scheduler::instance().clock());

	fprintf(stderr, "\ttx_state_: %x, rx_state_: %x, nav: %2.9f, idle: %d\n",
			tx_state_, rx_state_, nav_, is_idle());

	fprintf(
			stderr,
			"\tpktTx_: %lx, pktRx_: %lx, pktRTS_: %lx, pktCTRL_: %lx, pktBEACON_: %lx, pktASSOCREQ_: %lx, pktASSOCREP_: %lx, pktPROBEREQ_: %lx, pktPROBEREP_: %lx, pktAUTHENTICATE_: %lx, callback: %lx\n",
			(long) pktTx_, (long) pktRx_, (long) pktRTS_, (long) pktCTRL_,
			(long) pktBEACON_, (long) pktASSOCREQ_, (long) pktASSOCREP_,
			(long) pktPROBEREQ_, (long) pktPROBEREP_, (long) pktAUTHENTICATE_,
			(long) callback_);

	fprintf(stderr,
			"\tDefer: %d, Backoff: %d (%d), Recv: %d, Timer: %d Nav: %d\n",
			mhDefer_.busy(), mhBackoff_.busy(), mhBackoff_.paused(),
			mhRecv_.busy(), mhSend_.busy(), mhNav_.busy());
	fprintf(stderr, "\tBackoff Expire: %f\n", mhBackoff_.expire());
}

/* ======================================================================
 Packet Headers Routines
 ====================================================================== */
inline int Mac802_11::hdr_dst(char* hdr, int dst) {
	struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr;

	if (dst > -2) {
		if (bss_id() == ((int)IBSS_ID)) {
			STORE4BYTE(&dst, (dh->dh_ra));
		} else if (addr() == bss_id_) {
			if (find_client(dst) == 1 || (u_int32_t) dst == MAC_BROADCAST) {
				STORE4BYTE(&dst, (dh->dh_ra));
			} else {
				int dst_broadcast;
				dst_broadcast = MAC_BROADCAST;

				STORE4BYTE(&dst_broadcast, (dh->dh_ra));
				STORE4BYTE(&dst, (dh->dh_3a));
				dh->dh_fc.fc_to_ds = 1;
				dh->dh_fc.fc_from_ds = 1;
			}

		} else {

			STORE4BYTE(&bss_id_, (dh->dh_ra));
			STORE4BYTE(&dst, (dh->dh_3a));
		}
	}

	return (u_int32_t)ETHER_ADDR(dh->dh_ra);
}

inline int Mac802_11::hdr_src(char* hdr, int src) {
	struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr;
	if (src > -2)
		STORE4BYTE(&src, (dh->dh_ta));
	return ETHER_ADDR(dh->dh_ta);
}

inline int Mac802_11::hdr_type(char* hdr, u_int16_t type) {
	struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr;
	if (type)
		STORE2BYTE(&type,(dh->dh_body));
	return GET2BYTE(dh->dh_body);
}

/* ======================================================================
 Misc Routines
 ====================================================================== */
inline int Mac802_11::is_idle() {
	if (rx_state_ != MAC_IDLE)
		return 0;
	if (tx_state_ != MAC_IDLE)
		return 0;
	if (nav_ > Scheduler::instance().clock())
		return 0;

	return 1;
}

void Mac802_11::discard(Packet *p, const char* why) {
	hdr_mac802_11* mh = HDR_MAC802_11(p);
	hdr_cmn *ch = HDR_CMN(p);

	/* if the rcvd pkt contains errors, a real MAC layer couldn't
	 necessarily read any data from it, so we just toss it now */
	if (ch->error() != 0) {
		Packet::free(p);
		return;
	}

	switch (mh->dh_fc.fc_type) {
	case MAC_Type_Management:
		switch (mh->dh_fc.fc_subtype) {
		case MAC_Subtype_Auth:
			if ((u_int32_t)ETHER_ADDR(mh->dh_ra) == (u_int32_t)index_) {
				drop(p, why);
				return;
			}
			break;
			//		drop(p, why);
			//		return;
		case MAC_Subtype_AssocReq:
			if ((u_int32_t)ETHER_ADDR(mh->dh_ra) == (u_int32_t)index_) {
				drop(p, why);
				return;
			}
			break;
		case MAC_Subtype_AssocRep:
			break;
		case MAC_Subtype_ProbeReq:
			if ((u_int32_t)ETHER_ADDR(mh->dh_ra) == (u_int32_t)index_) {
				drop(p, why);
				return;
			}
			break;
		case MAC_Subtype_ProbeRep:
			break;
		case MAC_Subtype_80211_Beacon:
			break;
		default:
			fprintf(stderr, "invalid MAC Management subtype\n");
			exit(1);
		}
		break;
	case MAC_Type_Control:
		switch (mh->dh_fc.fc_subtype) {
		case MAC_Subtype_RTS:
			if ((u_int32_t)ETHER_ADDR(mh->dh_ta) == (u_int32_t)index_) {
				drop(p, why);
				return;
			}
			/* fall through - if necessary */
		case MAC_Subtype_CTS:
		case MAC_Subtype_ACK:
			if ((u_int32_t)ETHER_ADDR(mh->dh_ra) == (u_int32_t)index_) {
				drop(p, why);
				return;
			}
			break;
		default:
			fprintf(stderr, "invalid MAC Control subtype\n");
			exit(1);
		}
		break;
	case MAC_Type_Data:
		switch (mh->dh_fc.fc_subtype) {
		case MAC_Subtype_Data:
			if ((u_int32_t)ETHER_ADDR(mh->dh_ra) == (u_int32_t)index_ || (u_int32_t)ETHER_ADDR(mh->dh_ta) == (u_int32_t)index_ || ((u_int32_t)ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST && mh->dh_fc.fc_to_ds == 0)) {
				drop(p, why);
				return;
			}
			break;
		default:
			fprintf(stderr, "invalid MAC Data subtype\n");
			exit(1);
		}
		break;
	default:
		fprintf(stderr, "invalid MAC type (%x)\n", mh->dh_fc.fc_type);
		trace_pkt(p);
		exit(1);
	}
	Packet::free(p);
}

void Mac802_11::capture(Packet *p) {
	/*
	 * Update the NAV so that this does not screw
	 * up carrier sense.
	 */
	set_nav(usec(phymib_.getEIFS() + txtime(p)));
	Packet::free(p);
}

void Mac802_11::collision(Packet *p) {
	switch (rx_state_) {
	case MAC_RECV:
		// 15. QPART
		setRxState(MAC_COLL, p);
		//setRxState(MAC_COLL);
		// end 15
		/* fall through */
	case MAC_COLL:
		assert(pktRx_);
		assert(mhRecv_.busy());
		/*
		 *  Since a collision has occurred, figure out
		 *  which packet that caused the collision will
		 *  "last" the longest.  Make this packet,
		 *  pktRx_ and reset the Recv Timer if necessary.
		 */
		if (txtime(p) > mhRecv_.expire()) {
			mhRecv_.stop();
			discard(pktRx_, DROP_MAC_COLLISION);
			pktRx_ = p;
			mhRecv_.start(txtime(pktRx_));
		} else {
			discard(p, DROP_MAC_COLLISION);
		}
		break;
	default:
		assert(0);
	}
}

void Mac802_11::tx_resume() {
	double rTime;
	assert(mhSend_.busy() == 0);
	assert(mhDefer_.busy() == 0);

	if (pktCTRL_) {
		/*
		 *  Need to send a CTS or ACK.
		 */
		mhDefer_.start(phymib_.getSIFS());
	} else if (pktRTS_) {
		if (mhBackoff_.busy() == 0) {
			if (bugFix_timer_) {
				mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
			} else {
				// 16. QPART
				rTime = (Random::random() % cwQos_) * phymib_.getSlotTime();
				//mhDefer_.start(cw_, is_idle(), phymib_.getDIFS());
				//modification Bilel 22-11-2006
				mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
				//rTime = (Random::random() % cw_) * phymib_.getSlotTime();
				//mhDefer_.start( phymib_.getDIFS() + rTime);
				// end 16
			}
		}
	} else if (pktTx_) {
		if (mhBackoff_.busy() == 0) {
			hdr_cmn *ch = HDR_CMN(pktTx_);
			struct hdr_mac802_11 *mh = HDR_MAC802_11(pktTx_);

			if ((u_int32_t) ch->size() < macmib_.getRTSThreshold()
					|| (u_int32_t) ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST) {
				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
				} else {
					// 17. QPART
					if (is_qos(pktTx_)) {
						rTime = (Random::random() % cwQos_)
								* phymib_.getSlotTime();
					} else {
						rTime = (Random::random() % cwBe_)
								* phymib_.getSlotTime();
					}
					mhDefer_.start(phymib_.getDIFS() + rTime);
					//					rTime = (Random::random() % cw_) * phymib_.getSlotTime();
					//					mhDefer_.start(phymib_.getDIFS() + rTime);
					// end 17
				}
			} else {
				mhDefer_.start(phymib_.getSIFS());
			}
		}
	} else if (callback_) {
		Handler *h = callback_;
		callback_ = 0;
		h->handle((Event*) 0);
	}
	// 18. QPART
	Packet *p=Packet::alloc();
	setTxState(MAC_IDLE, p);
	free(p);
	//setTxState(MAC_IDLE);
	// end 18
}

void Mac802_11::rx_resume() {
	assert(pktRx_ == 0);
	assert(mhRecv_.busy() == 0);
	// 19. QPART
	setRxState(MAC_IDLE, p);
	free(p);
	//setRxState(MAC_IDLE);
	// end 19
}

/* ======================================================================
 Timer Handler Routines
 ====================================================================== */
void Mac802_11::backoffHandler() {
	if (addr() != bss_id_ && infra_mode_ == 1) {
		if (check_pktPROBEREQ() == 0)
			return;
		if (check_pktAUTHENTICATE() == 0)
			return;
		if (check_pktASSOCREQ() == 0)
			return;
	}

	if (pktCTRL_) {
		assert(mhSend_.busy() || mhDefer_.busy());
		return;
	}

	if (addr() == bss_id_) {
		if (pktPROBEREP_ && priority_queue[head] == 1) {
			if (check_pktPROBEREP() == 0)
				return;
		} else if (pktBEACON_ && priority_queue[head] == 2) {
			if (check_pktBEACON() == 0) {
				return;
			}
		} else if (pktAUTHENTICATE_ && priority_queue[head] == 3) {
			if (check_pktAUTHENTICATE() == 0)
				return;
		} else if (pktASSOCREP_ && priority_queue[head] == 4) {
			if (check_pktASSOCREP() == 0)
				return;
		}
	}

	if (check_pktRTS() == 0)
		return;
	if (check_pktTx() == 0)
		return;
}

void Mac802_11::BeaconHandler() {

	mhBeacon_.start(phymib_.getBeaconInterval());
	sendBEACON(index_);

}

// Probe timer is used for multiple purposes. It can be set to 4 different values
// Probe Delay, MinChannelTime and MaxChannelTime -  for Active Scanning
// ChannelTime - Passive Scanning


void Mac802_11::ProbeHandler() {
	if (ScanType_ == ACTIVE) {
		if ( (bss_id_ == (int)IBSS_ID || handoff == 1) && OnMinChannelTime == 0
				&& Recv_Busy_ == 0 && OnMaxChannelTime == 0) {
			if (strongest_ap() < 0) { // Probe delay over - Active Scan starts here, when the ap_table has not been built yet
				sendPROBEREQ(MAC_BROADCAST);
				return;
			} else {
				checkAssocAuthStatus(); // MaxChannelTime Over - Handoff is taking place and ap_table is built, complete authentication and (re)association
				return;
			}
		} else if (OnMinChannelTime == 1 && Recv_Busy_ == 1 && OnMaxChannelTime
				== 0) {
			// MinChannelTime Over - receiver indicated busy before timer expiry, hence Probe timer should be continued for MaxChannelTime, to reeive all probe responses
			OnMinChannelTime = 0;
			OnMaxChannelTime = 1;
			mhProbe_.start(macmib_.getMaxChannelTime());
			return;
		} else if (OnMinChannelTime == 0 && Recv_Busy_ == 1 && OnMaxChannelTime
				== 1) {
			// MaxChannelTime Over - Active Scanning is over, start authentication and association
			OnMaxChannelTime = 0;
			Recv_Busy_ = 0;
			if (strongest_ap() > -1)
				active_scan();
			else
				printf("No APs in range\n");
			return;
		} else if (OnMinChannelTime == 1 && Recv_Busy_ == 0 && OnMaxChannelTime
				== 0) {
			//printf("Out of range of any Access Point or channel without APs\n");
			OnMinChannelTime = 0;
			deletelist(); //  MinChannelTime Over - Delete ap_table
			return;
		}
	} else {
		if (ScanType_ == PASSIVE && bss_id_ == (int)IBSS_ID) {
			//  ChannelTime Over - Passive Scanning is over, start authentication and association
			passive_scan(); // 
			return;
		}
	}
	if (bss_id_ != (int)IBSS_ID && !mhProbe_.busy()) {
		// Start Authentication and Association
		checkAssocAuthStatus();
	}
}

void Mac802_11::deferHandler() {
	assert(pktCTRL_ || pktRTS_ || pktTx_);

	if (check_pktCTRL() == 0)
		return;
	assert(mhBackoff_.busy() == 0);
	if (check_pktRTS() == 0)
		return;
	if (check_pktTx() == 0)
		return;
}

// 20. QPART
//---------------------------------------------BILEL
void Mac802_11::deferHandler2() {
	/*	assert(pktCTRL_ || pktRTS_ || pktTx_);

	 if(check_pktCTRL() == 0)
	 return;

	 assert(mhBackoff_.busy() == 0);
	 //if (mhBackoff_.busy() != 0)
	 //{
	 //	printf("deferHandler:mhBackoff_ busy!\n");
	 //	return;
	 //}
	 if(check_pktRTS() == 0)
	 return;

	 if(check_pktTx() == 0)
	 return;
	 */
	printf("je suis ici defer handler2! ! ! \n");
	//mhDefer2_.stop();
	//return ;
}
//----------------------------------------------/BILEL
// end 20

void Mac802_11::navHandler() {
	if (is_idle() && mhBackoff_.paused())
		mhBackoff_.resume(phymib_.getDIFS());
}

void Mac802_11::recvHandler() {
	recv_timer();
}

void Mac802_11::sendHandler() {
	send_timer();
}

void Mac802_11::txHandler() {
	if (EOTtarget_) {
		assert(eotPacket_);
		EOTtarget_->recv(eotPacket_, (Handler *) 0);
		eotPacket_ = NULL;
	}
	tx_active_ = 0;
}

/* ======================================================================
 The "real" Timer Handler Routines
 ====================================================================== */
void Mac802_11::send_timer() {
	switch (tx_state_) {

	case MAC_MGMT:
		if (pktAUTHENTICATE_) {
			assert(pktAUTHENTICATE_);
			Packet::free(pktAUTHENTICATE_);
			pktAUTHENTICATE_ = 0;
			if (addr() == bss_id_) {
				if (end() > (head + 1)) {
					shift_priority_queue();
					assert(mhBackoff_.busy() == 0);
					mhBackoff_.start(cw_, is_idle());
				} else
					priority_queue[head] = 0;
			} else
				checkAssocAuthStatus();
			break;
		}
		if (pktASSOCREQ_) {
			assert(pktASSOCREQ_);
			Packet::free(pktASSOCREQ_);
			pktASSOCREQ_ = 0;
			checkAssocAuthStatus();
			break;
		}
		if (pktASSOCREP_) {
			assert(pktASSOCREP_);
			Packet::free(pktASSOCREP_);
			pktASSOCREP_ = 0;
			if (end() > (head + 1)) {
				shift_priority_queue();
				assert(mhBackoff_.busy() == 0);
				mhBackoff_.start(cw_, is_idle());
			} else
				priority_queue[head] = 0;
			break;
		}
		if (pktPROBEREQ_) {
			assert(pktPROBEREQ_);
			Packet::free(pktPROBEREQ_);
			pktPROBEREQ_ = 0;
			break;
		}
		if (pktPROBEREP_) {
			assert(pktPROBEREP_);
			Packet::free(pktPROBEREP_);
			pktPROBEREP_ = 0;
			if (end() > (head + 1)) {
				shift_priority_queue();
				assert(mhBackoff_.busy() == 0);
				mhBackoff_.start(cw_, is_idle());
			} else
				priority_queue[head] = 0;
			break;
		}
	case MAC_BCN:
		assert(pktBEACON_);
		Packet::free(pktBEACON_);
		pktBEACON_ = 0;
		if (end() > (head + 1)) {
			shift_priority_queue();
			assert(mhBackoff_.busy() == 0);
			mhBackoff_.start(cw_, is_idle());
		} else
			priority_queue[head] = 0;
		break;

	case MAC_RTS:
		RetransmitRTS();
		break;
		/*
		 * Sent a CTS, but did not receive a DATA packet.
		 */
	case MAC_CTS:
		assert(pktCTRL_);
		Packet::free(pktCTRL_);
		pktCTRL_ = 0;
		break;
		/*
		 * Sent DATA, but did not receive an ACK packet.
		 */
	case MAC_SEND:
		RetransmitDATA();
		break;
		/*
		 * Sent an ACK, and now ready to resume transmission.
		 */
	case MAC_ACK:
		assert(pktCTRL_);
		Packet::free(pktCTRL_);
		pktCTRL_ = 0;
		break;
	case MAC_IDLE:
		break;
	default:
		assert(0);
	}
	tx_resume();
}

/* ======================================================================
 Outgoing Packet Routines
 ====================================================================== */
int Mac802_11::check_pktCTRL() {
	struct hdr_mac802_11 *mh;
	double timeout;

	if (pktCTRL_ == 0)
		return -1;
	if (tx_state_ == MAC_CTS || tx_state_ == MAC_ACK)
		return -1;

	mh = HDR_MAC802_11(pktCTRL_);

	switch (mh->dh_fc.fc_subtype) {
	/*
	 *  If the medium is not IDLE, don't send the CTS.
	 */
	case MAC_Subtype_CTS:
		if (!is_idle()) {
			discard(pktCTRL_, DROP_MAC_BUSY);
			pktCTRL_ = 0;
			return 0;
		}

		// 21. QPART
		setTxState(MAC_CTS, pktCTRL_);
		//setTxState(MAC_CTS);
		// end 21
		/*
		 * timeout:  cts + data tx time calculated by
		 *           adding cts tx time to the cts duration
		 *           minus ack tx time -- this timeout is
		 *           a guess since it is unspecified
		 *           (note: mh->dh_duration == cf->cf_duration)
		 */
		timeout = txtime(phymib_.getCTSlen(), basicRate_)
				+ DSSS_MaxPropagationDelay // XXX
				+ sec(mh->dh_duration) + DSSS_MaxPropagationDelay // XXX
				- phymib_.getSIFS() - txtime(phymib_.getACKlen(), basicRate_);
		break;
		/*
		 * IEEE 802.11 specs, section 9.2.8
		 * Acknowledments are sent after an SIFS, without regard to
		 * the busy/idle state of the medium.
		 */
	case MAC_Subtype_ACK:
		// 22. QPART
		setTxState(MAC_ACK, pktCTRL_);
		//setTxState(MAC_ACK);
		// end 22
		timeout = txtime(phymib_.getACKlen(), basicRate_);
		break;
	default:
		fprintf(stderr, "check_pktCTRL:Invalid MAC Control subtype\n");
		exit(1);
	}
	transmit(pktCTRL_, timeout);
	return 0;
}

int Mac802_11::check_pktRTS() {
	struct hdr_mac802_11 *mh;
	double timeout;

	assert(mhBackoff_.busy() == 0);

	if (pktRTS_ == 0)
		return -1;
	mh = HDR_MAC802_11(pktRTS_);

	switch (mh->dh_fc.fc_subtype) {
	case MAC_Subtype_RTS:
		if (!is_idle()) {
			// 23. QPART
			if (is_qos(pktRTS_)) {
				inc_cwQos();
			} else {
				inc_cwBe();
			}
			/*switch (ih->fid_){
			 case 1 : mhBackoff_.start(cwos_, is_idle());
			 case 0 : mhBackoff_.start(cw_, is_idle());
			 }*/
			mhBackoff_.start(cwQos_, is_idle());
			//			inc_cw();
			//			mhBackoff_.start(cw_, is_idle());
			// end 23
			return 0;
		}
		// 24. QPART
		setTxState(MAC_RTS, pktCTRL_);
		//setTxState(MAC_RTS);
		// end 24
		timeout = txtime(phymib_.getRTSlen(), basicRate_)
				+ DSSS_MaxPropagationDelay // XXX
				+ phymib_.getSIFS() + txtime(phymib_.getCTSlen(), basicRate_)
				+ DSSS_MaxPropagationDelay;
		break;
	default:
		fprintf(stderr, "check_pktRTS:Invalid MAC Control subtype\n");
		exit(1);
	}
	transmit(pktRTS_, timeout);

	return 0;
}

int Mac802_11::check_pktTx() {

	struct hdr_mac802_11 *mh;
	double timeout;

	assert(mhBackoff_.busy() == 0);

	if (pktTx_ == 0)
		return -1;

	mh = HDR_MAC802_11(pktTx_);

	if (addr() != bss_id_ && bss_id_ != (int)IBSS_ID) {
		if (handoff == 0)
			STORE4BYTE(&bss_id_, (mh->dh_ra));
	}

	switch (mh->dh_fc.fc_subtype) {
	case MAC_Subtype_Data:
		if (!is_idle()) {
			sendRTS(ETHER_ADDR(mh->dh_ra));
			// 25. QPART
			//			inc_cw();
			//			mhBackoff_.start(cw_, is_idle());
			if (is_qos(pktTx_)) {
				mhBackoff_.start(cwQos_, is_idle());
				//--------------------
				//printf("cw qos dans checkpkt = %d\n", cwQos_);
			} else {
				mhBackoff_.start(cwBe_, is_idle());
				//printf("cw be dans checkpkt = %d\n", cw_);

			}
			// end 25
			return 0;
		}
		// 26. QPART
		setTxState(MAC_SEND, pktTx_);
		//setTxState(MAC_SEND);
		// end 26

		if ((u_int32_t)ETHER_ADDR(mh->dh_ra) != MAC_BROADCAST)
			timeout = txtime(pktTx_) + DSSS_MaxPropagationDelay // XXX
					+ phymib_.getSIFS() + txtime(phymib_.getACKlen(),
					basicRate_) + DSSS_MaxPropagationDelay; // XXX
		else
			timeout = txtime(pktTx_);
		break;
	default:
		fprintf(stderr, "check_pktTx:Invalid MAC Control subtype\n");
		exit(1);
	}
	transmit(pktTx_, timeout);
	return 0;
}
/*
 * Low-level transmit functions that actually place the packet onto
 * the channel.
 */
void Mac802_11::sendRTS(int dst) {
	Packet *p = Packet::alloc();
	hdr_cmn* ch = HDR_CMN(p);
	struct rts_frame *rf = (struct rts_frame*)p->access(hdr_mac::offset_);

	assert(pktTx_);
	assert(pktRTS_ == 0);

	/*
	 *  If the size of the packet is larger than the
	 *  RTSThreshold, then perform the RTS/CTS exchange.
	 */
	if ( (u_int32_t) HDR_CMN(pktTx_)->size() < macmib_.getRTSThreshold() || (u_int32_t) dst
			== MAC_BROADCAST) {
		Packet::free(p);
		return;
	}

	ch->uid() = 0;
	ch->ptype() = PT_MAC;
	ch->size() = phymib_.getRTSlen();
	ch->iface() = -2;
	ch->error() = 0;

	// 27. QPART
	//printf("\n\n SEND RTS    %f", Fn);
	ch->Fn() = Fn;
	// end 27

	bzero(rf, MAC_HDR_LEN);

	rf->rf_fc.fc_protocol_version = MAC_ProtocolVersion;
	rf->rf_fc.fc_type = MAC_Type_Control;
	rf->rf_fc.fc_subtype = MAC_Subtype_RTS;
	rf->rf_fc.fc_to_ds = 0;
	rf->rf_fc.fc_from_ds = 0;
	rf->rf_fc.fc_more_frag = 0;
	rf->rf_fc.fc_retry = 0;
	rf->rf_fc.fc_pwr_mgt = 0;
	rf->rf_fc.fc_more_data = 0;
	rf->rf_fc.fc_wep = 0;
	rf->rf_fc.fc_order = 0;

	//rf->rf_duration = RTS_DURATION(pktTx_);
	STORE4BYTE(&dst, (rf->rf_ra));

	/* store rts tx time */
	ch->txtime() = txtime(ch->size(), basicRate_);

	STORE4BYTE(&index_, (rf->rf_ta));

	/* calculate rts duration field */
	rf->rf_duration = usec(phymib_.getSIFS() + txtime(phymib_.getCTSlen(),
			basicRate_) + phymib_.getSIFS() + txtime(pktTx_)
			+ phymib_.getSIFS() + txtime(phymib_.getACKlen(), basicRate_));
	pktRTS_ = p;
}

void Mac802_11::sendCTS(int dst, double rts_duration) {
	Packet *p = Packet::alloc();
	hdr_cmn* ch = HDR_CMN(p);
	struct cts_frame *cf = (struct cts_frame*)p->access(hdr_mac::offset_);

	assert(pktCTRL_ == 0);

	ch->uid() = 0;
	ch->ptype() = PT_MAC;
	ch->size() = phymib_.getCTSlen();

	// 28. QPART
	ch->Fn() = Fn;
	// end 28

	ch->iface() = -2;
	ch->error() = 0;
	//ch->direction() = hdr_cmn::DOWN;
	bzero(cf, MAC_HDR_LEN);

	cf->cf_fc.fc_protocol_version = MAC_ProtocolVersion;
	cf->cf_fc.fc_type = MAC_Type_Control;
	cf->cf_fc.fc_subtype = MAC_Subtype_CTS;
	cf->cf_fc.fc_to_ds = 0;
	cf->cf_fc.fc_from_ds = 0;
	cf->cf_fc.fc_more_frag = 0;
	cf->cf_fc.fc_retry = 0;
	cf->cf_fc.fc_pwr_mgt = 0;
	cf->cf_fc.fc_more_data = 0;
	cf->cf_fc.fc_wep = 0;
	cf->cf_fc.fc_order = 0;

	//cf->cf_duration = CTS_DURATION(rts_duration);
	STORE4BYTE(&dst, (cf->cf_ra));

	/* store cts tx time */
	ch->txtime() = txtime(ch->size(), basicRate_);

	/* calculate cts duration */
	cf->cf_duration = usec(sec(rts_duration) - phymib_.getSIFS() - txtime(
			phymib_.getCTSlen(), basicRate_));

	pktCTRL_ = p;

}

void Mac802_11::sendACK(int dst) {
	Packet *p = Packet::alloc();
	hdr_cmn* ch = HDR_CMN(p);
	struct ack_frame *af = (struct ack_frame*)p->access(hdr_mac::offset_);

	assert(pktCTRL_ == 0);

	ch->uid() = 0;
	ch->ptype() = PT_MAC;
	// CHANGE WRT Mike's code
	ch->size() = phymib_.getACKlen();
	ch->iface() = -2;
	ch->error() = 0;

	// 29. QPART
	ch->Fn_ = Fn;
	// end 29

	bzero(af, MAC_HDR_LEN);

	af->af_fc.fc_protocol_version = MAC_ProtocolVersion;
	af->af_fc.fc_type = MAC_Type_Control;
	af->af_fc.fc_subtype = MAC_Subtype_ACK;
	af->af_fc.fc_to_ds = 0;
	af->af_fc.fc_from_ds = 0;
	af->af_fc.fc_more_frag = 0;
	af->af_fc.fc_retry = 0;
	af->af_fc.fc_pwr_mgt = 0;
	af->af_fc.fc_more_data = 0;
	af->af_fc.fc_wep = 0;
	af->af_fc.fc_order = 0;

	// 30. QPART
	af->test = 111; //99999999999999999999999999999999999999999999999999999999999999999999999999999
	// end 30

	//af->af_duration = ACK_DURATION();
	STORE4BYTE(&dst, (af->af_ra));

	/* store ack tx time */
	ch->txtime() = txtime(ch->size(), basicRate_);

	/* calculate ack duration */
	af->af_duration = 0;

	pktCTRL_ = p;
}

void Mac802_11::sendDATA(Packet *p) {
	hdr_cmn* ch = HDR_CMN(p);
	// 31. QPART
	struct hdr_ip *ih = HDR_IP(p);
	// end 31
	struct hdr_mac802_11* dh = HDR_MAC802_11(p);
	u_int32_t dst= ETHER_ADDR(dh->dh_ra);

	// 32. QPART
	affichecw(listcw);
	// end 32

	assert(pktTx_ == 0);

	/*
	 * Update the MAC header
	 */
	ch->size() += phymib_.getHdrLen11();

	// 33. QPART
	ch->Fn_ = Fn;
	//printf("Fn dans send data = %f\n", ch->Fn_);
	ch->direction_ = hdr_cmn::DOWN; //*************************------------------------------
	//printf("Fn ds mac 801.11 == %f\n",ch->Fn_);
	// end 33

	dh->dh_fc.fc_protocol_version = MAC_ProtocolVersion;
	dh->dh_fc.fc_type = MAC_Type_Data;
	dh->dh_fc.fc_subtype = MAC_Subtype_Data;
	if (bss_id_ != (int)IBSS_ID ) {
		if (index_ == ap_addr) {
			if (dh->dh_fc.fc_to_ds == 0) {
				if (find_client(dst) == 1 || dst == MAC_BROADCAST) {
					dh->dh_fc.fc_to_ds = 0;
					dh->dh_fc.fc_from_ds = 1;
				}
			}
		} else {
			dh->dh_fc.fc_to_ds = 1;
			dh->dh_fc.fc_from_ds = 0;
		}
	} else {
		dh->dh_fc.fc_to_ds = 0;
		dh->dh_fc.fc_from_ds = 0;
	}

	dh->dh_fc.fc_more_frag = 0;
	dh->dh_fc.fc_retry = 0;
	dh->dh_fc.fc_pwr_mgt = 0;
	dh->dh_fc.fc_more_data = 0;
	dh->dh_fc.fc_wep = 0;
	dh->dh_fc.fc_order = 0;

	/* store data tx time */
	ch->txtime() = txtime(ch->size(), dataRate_);

	if ((u_int32_t)ETHER_ADDR(dh->dh_ra) != MAC_BROADCAST) {
		/* store data tx time for unicast packets */
		ch->txtime() = txtime(ch->size(), dataRate_);

		dh->dh_duration = usec(txtime(phymib_.getACKlen(), basicRate_)
				+ phymib_.getSIFS());

	} else {
		/* store data tx time for broadcast packets (see 9.6) */
		ch->txtime() = txtime(ch->size(), basicRate_);

		dh->dh_duration = 0;
	}

	// 34. QPART
	//les pkt data contiennent un champs date pour calculer la prio avant de transmettre
	if (ch->size() >= 1000) {
		if (ih->ttl_ == 32) {
			ch->date = CURRENT_TIME;
		}
	}
	// end 34

	pktTx_ = p;
}

/* ======================================================================
 Retransmission Routines
 ====================================================================== */
void Mac802_11::RetransmitRTS() {
	assert(pktTx_);
	assert(pktRTS_);
	assert(mhBackoff_.busy() == 0);
	macmib_.RTSFailureCount++;

	ssrc_ += 1; // STA Short Retry Count

	if (ssrc_ >= macmib_.getShortRetryLimit()) {
		discard(pktRTS_, DROP_MAC_RETRY_COUNT_EXCEEDED);
		pktRTS_ = 0;
		/* tell the callback the send operation failed 
		 before discarding the packet */
		hdr_cmn *ch = HDR_CMN(pktTx_);
		if (ch->xmit_failure_) {
			/*
			 *  Need to remove the MAC header so that 
			 *  re-cycled packets don't keep getting
			 *  bigger.
			 */
			ch->size() -= phymib_.getHdrLen11();
			ch->xmit_reason_ = XMIT_REASON_RTS;
			ch->xmit_failure_(pktTx_->copy(), ch->xmit_failure_data_);
		}
		discard(pktTx_, DROP_MAC_RETRY_COUNT_EXCEEDED);
		pktTx_ = 0;
		ssrc_ = 0;
		// 35. QPART
		if (is_qos(pktTx_)) {
			rst_cwQos();
		} else {
			rst_cwBe();
		}
		//rst_cw();
		// end 35
	} else {
		struct rts_frame *rf;
		rf = (struct rts_frame*)pktRTS_->access(hdr_mac::offset_);
		rf->rf_fc.fc_retry = 1;

		// 36. QPART
		//inc_cw();
		//mhBackoff_.start(cw_, is_idle());
		if (is_qos(pktRTS_)) {
			mhBackoff_.start(cwQos_, is_idle());
			//--------------------
			//printf("cw qos dans RetransmitRTS = %d\n", cwQos_);
		} else {
			mhBackoff_.start(cwBe_, is_idle());
			//-----------------
			//printf("cw be dans RetransmitRTS = %d\n", cwBe_);
		}
		// end 36
	}
}

void Mac802_11::RetransmitDATA() {
	struct hdr_cmn *ch;
	struct hdr_mac802_11 *mh;
	u_int32_t *rcount, thresh;
	assert(mhBackoff_.busy() == 0);

	assert(pktTx_);
	assert(pktRTS_ == 0);

	ch = HDR_CMN(pktTx_);
	mh = HDR_MAC802_11(pktTx_);

	/*
	 *  Broadcast packets don't get ACKed and therefore
	 *  are never retransmitted.
	 */
	if ((u_int32_t)ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST) {
		Packet::free(pktTx_);
		pktTx_ = 0;

		/*
		 * Backoff at end of TX.
		 */
		// 37. QPART
		rst_cwBe();
		//rst_cw();
		//mhBackoff_.start(cw_, is_idle());
		// end 37

		return;
	}

	macmib_.ACKFailureCount++;

	if ((u_int32_t) ch->size() <= macmib_.getRTSThreshold()) {
		rcount = &ssrc_;
		thresh = macmib_.getShortRetryLimit();
	} else {
		rcount = &slrc_;
		thresh = macmib_.getLongRetryLimit();
	}

	(*rcount)++;

	if (*rcount == 3 && handoff == 0) {
		//start handoff process
		printf("Client %d: Handoff Attempted\n", index_);
		associated = 0;
		authenticated = 0;
		handoff = 1;
		ScanType_ = ACTIVE;
		sendPROBEREQ(MAC_BROADCAST);
		return;
	}
	if (*rcount >= thresh) {
		/* IEEE Spec section 9.2.3.5 says this should be greater than
		 or equal */
		macmib_.FailedCount++;
		/* tell the callback the send operation failed 
		 before discarding the packet */
		hdr_cmn *ch = HDR_CMN(pktTx_);
		if (ch->xmit_failure_) {
			ch->size() -= phymib_.getHdrLen11();
			ch->xmit_reason_ = XMIT_REASON_ACK;
			ch->xmit_failure_(pktTx_->copy(), ch->xmit_failure_data_);
		}

		discard(pktTx_, DROP_MAC_RETRY_COUNT_EXCEEDED);
		pktTx_ = 0;
		*rcount = 0;
		// 38. QPART
		rst_cwBe();
		//rst_cw();
		// end 38
	} else {
		struct hdr_mac802_11 *dh;
		dh = HDR_MAC802_11(pktTx_);
		dh->dh_fc.fc_retry = 1;

		sendRTS(ETHER_ADDR(mh->dh_ra));
		// 39. QPART
		//inc_cw();
		//mhBackoff_.start(cw_, is_idle());
		if (is_qos(pktTx_)) {
			mhBackoff_.start(cwQos_, is_idle());
			//--------------------
			//printf("cw qos dans RetransmitDATA = %d\n", cwQos_);
		} else {
			mhBackoff_.start(cwBe_, is_idle());
			//--------------------
			//printf("cw be dans RetransmitDATA = %d\n", cwBe_);
		}
		//		inc_cw();
		//		mhBackoff_.start(cw_, is_idle());
		// end 39
	}
}

void Mac802_11::RetransmitPROBEREP() {
	double rTime;

	if (mhBackoff_.busy() == 0) {
		if (is_idle()) {
			if (mhDefer_.busy() == 0) {
				/*
				 * If we are already deferring, there is no
				 * need to reset the Defer timer.
				 */
				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
					priority_queue[head] = 1;
				} else {
					rTime = (Random::random() % cw_) * (phymib_.getSlotTime());
					mhDefer_.start(phymib_.getDIFS() + rTime);
				}
			}
		} else {
			/*
			 * If the medium is NOT IDLE, then we start
			 * the backoff timer.
			 */
			mhBackoff_.start(cw_, is_idle());
			priority_queue[head] = 1;

		}

	} else {
		priority_queue[end()] = 1;
	}

}

void Mac802_11::RetransmitAUTHENTICATE() {
	double rTime;

	if (mhBackoff_.busy() == 0) {
		if (is_idle()) {
			if (mhDefer_.busy() == 0) {
				/*
				 * If we are already deferring, there is no
				 * need to reset the Defer timer.
				 */
				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
					priority_queue[head] = 3;
				} else {
					rTime = (Random::random() % cw_) * (phymib_.getSlotTime());
					mhDefer_.start(phymib_.getDIFS() + rTime);
				}
			}
		} else {
			/*
			 * If the medium is NOT IDLE, then we start
			 * the backoff timer.
			 */
			mhBackoff_.start(cw_, is_idle());
			priority_queue[head] = 3;

		}

	} else {
		priority_queue[end()] = 3;
	}

}

void Mac802_11::RetransmitASSOCREP() {
	double rTime;

	if (mhBackoff_.busy() == 0) {
		if (is_idle()) {
			if (mhDefer_.busy() == 0) {
				/*
				 * If we are already deferring, there is no
				 * need to reset the Defer timer.
				 */
				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
					priority_queue[head] = 4;
				} else {
					rTime = (Random::random() % cw_) * (phymib_.getSlotTime());
					mhDefer_.start(phymib_.getDIFS() + rTime);
				}
			}
		} else {
			/*
			 * If the medium is NOT IDLE, then we start
			 * the backoff timer.
			 */
			mhBackoff_.start(cw_, is_idle());
			priority_queue[head] = 4;

		}

	} else {
		priority_queue[end()] = 4;
	}

}
/* ======================================================================
 Incoming Packet Routines
 ====================================================================== */
void Mac802_11::send(Packet *p, Handler *h) {
	double rTime;
	struct hdr_mac802_11* dh = HDR_MAC802_11(p);

	EnergyModel *em = netif_->node()->energy_model();
	if (em && em->sleep()) {
		em->set_node_sleep(0);
		em->set_node_state(EnergyModel::INROUTE);
	}

	callback_ = h;
	sendDATA(p);
	sendRTS(ETHER_ADDR(dh->dh_ra));

	/*
	 * Assign the data packet a sequence number.
	 */
	dh->dh_scontrol = sta_seqno_++;

	/*
	 *  If the medium is IDLE, we must wait for a DIFS
	 *  Space before transmitting.
	 */

	if (mhBackoff_.busy() == 0) {
		if (is_idle()) {
			if (mhDefer_.busy() == 0) {
				/*
				 * If we are already deferring, there is no
				 * need to reset the Defer timer.
				 */
				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
				} else {
					// 40. QPART
					if (is_qos(p)) {
						rTime = (Random::random() % cwQos_)
								* (phymib_.getSlotTime());
					} else {
						rTime = (Random::random() % cwBe_)
						// end 40
								* (phymib_.getSlotTime());
					}
					//rTime = (Random::random() % cw_) * (phymib_.getSlotTime());
					mhDefer_.start(phymib_.getDIFS() + rTime);
					// end 40
				}
			}
		} else {
			/*
			 * If the medium is NOT IDLE, then we start
			 * the backoff timer.
			 */
			// 41. QPART
			//	mhBackoff_.start(cw_, is_idle());
			if (is_qos(p)) {
				//cwQos_ = findCW(listcw, ih->fid_);//12.12
				mhBackoff_.start(cwQos_, is_idle());
				//--------------------
				//printf("cw qos dans send = %d\n", cwQos_);
			} else {
				mhBackoff_.start(cwBe_, is_idle());
				//------------------
				//printf("cw be dans send = %d\n", cwBe_);
			}
			// end 41
		}
	}

}

// 42. QPART
/*============================================================================================
 Mac802_11::lookupband(Band* , int ,int ,float)
 void Mac802_11::insertband(Band** ,int ,int ,float )
 void Mac802_11::afficheband(Band*)
 =============================================================================================*/

bool lookupband(Band *p, int src, ns_addr_t dst) {
	Band *pcour = (Band *)malloc(sizeof(Band));
	pcour = p;

	//Col *e;
	if (pcour==NULL)
		return false;

	while (pcour) {
		if ((pcour->src == src) && pcour->dst.isEqual(dst)) {
			return true;
		}
		pcour=pcour->next;
	}
	return false;
}

void insertband(Band **p, int src, ns_addr_t dst, float Fn) {
	Band *pcour = (Band *)malloc(sizeof(Band));
	//if(!pcour) return;	//Si l'allocation a �chou�e
	pcour = *p;
	if (lookupband(*p, src, dst)) { //si la src et la dst  existent  deja alors calcul_seuil
		while (pcour->src != src) //&& (pcour->dst != dst))
		{
			pcour = pcour->next;
		}
		pcour->Fn = Fn;
	} else //si la dsst et la src n'existent pas, il suffit de mettre a jour sa periorit�
	{
		//printf("Fn n existe pas!!! je le cree\n");
		while (pcour->next != NULL) {
			pcour = pcour->next;
		}
		Band *e = (Band *)malloc(sizeof(Band));
		//if(!e) return;	//Si l'allocation a �chou�e
		e->src=src;
		e->dst=dst;
		e->Fn=Fn;
		e->next=NULL;
		pcour->next = e;
	}
}

Band findband(Band *p, int src, ns_addr_t dst) {
	//Band pcour;
	Band *pcour = (Band *)malloc(sizeof(Band));
	//if(!pcour) return;	/*Si l'allocation a �chou�e */
	*pcour = *p;
	//if( p==NULL)
	//	return false;

	while (pcour) {
		if ( (pcour->src == src) && pcour->dst.isEqual(dst)) {
			return *pcour;
		}
		pcour=pcour->next;
	}
	//return false;
}

// end 42

void Mac802_11::recv(Packet *p, Handler *h) {
	// 43. QPART
	//Prio *pcour = (Prio *)malloc(sizeof(Prio));
	//bool test=false;

	//la reception se fait ds deux sens soit
	//	*en provenance d'une couche superieur donc son sens de propagation est mis a DOWN
	//	*en provenance du canal (plus precisemen de la couche physique) donc va passer vers les couches hautes du //	 noeud la direction est UP
	struct hdr_ip *ih = HDR_IP(p);
	// end 43
	struct hdr_cmn *hdr = HDR_CMN(p);
	/*
	 * Sanity Check
	 */
	assert(initialized());

	/*
	 *  Handle outgoing packets.
	 */
	if (hdr->direction() == hdr_cmn::DOWN) {
		// 44. QPART
		if (ih->fid_ > 10) {
			//printf("size qos mac = %d\n",hdr->size());
			Qn=ih->qn_;
			pr = ih->prio_;
			//printf("priorite du qos  =  %d\n",pr);
			//printf("taille prio ds mac  =  %d\n ", ih->prio_);

			//int ALO = prior->fid;
			//printf("=========================================== %d\n", ALO);

		}
		//12.12
		//--------------------------12.12 bilel
		int tempof;
		int tempoc;
		tempof = ih->fid_;
		tempoc = cwQos_; //la premiere valeur de cw QOS

		if (tempof >=11) //flux QOS
		{
			insertcw(&listcw, tempof, tempoc);
			if (lookupfid(listcw, tempof) ) {//flux  existe deja ds la liste cwQOS recoit la valeur dans la liste dans la liste
				cwQos_prec = findCW(listcw, tempof);
			}

		}
		//cwQos_ = findCW(listcw, ih->fid_);
		//--------------------------12.12 bilel
		//fin 12.12
		send(p, h);
		return;
	}
	// end 44
	/*
	 *  Handle incoming packets.
	 *
	 *  We just received the 1st bit of a packet on the network
	 *  interface.
	 *
	 */

	/*
	 *  If the interface is currently in transmit mode, then
	 *  it probably won't even see this packet.  However, the
	 *  "air" around me is BUSY so I need to let the packet
	 *  proceed.  Just set the error flag in the common header
	 *  to that the packet gets thrown away.
	 */
	if (tx_active_ && hdr->error() == 0) {
		hdr->error() = 1;
	}

	if (rx_state_ == MAC_IDLE) {
		// 45. QPART
		//setRxState(MAC_RECV);
		setRxState(MAC_RECV, p);
		// end 45
		pktRx_ = p;
		/*
		 * Schedule the reception of this packet, in
		 * txtime seconds.
		 */
		if (mhProbe_.busy() && OnMinChannelTime) {
			Recv_Busy_ = 1; // Receiver busy indication for Probe Timer 
		}

		mhRecv_.start(txtime(p));
	} else {
		/*
		 *  If the power of the incoming packet is smaller than the
		 *  power of the packet currently being received by at least
		 *  the capture threshold, then we ignore the new packet.
		 */
		if (pktRx_->txinfo_.RxPr / p->txinfo_.RxPr >= p->txinfo_.CPThresh) {
			capture(p);
		} else {
			collision(p);
		}
	}
}

void Mac802_11::recv_timer() {
	u_int32_t src;
	hdr_cmn *ch = HDR_CMN(pktRx_);
	hdr_mac802_11 *mh = HDR_MAC802_11(pktRx_);
	u_int32_t dst= ETHER_ADDR(mh->dh_ra);
	u_int32_t ap_dst= ETHER_ADDR(mh->dh_3a);
	u_int8_t type = mh->dh_fc.fc_type;
	u_int8_t subtype = mh->dh_fc.fc_subtype;

	assert(pktRx_);
	assert(rx_state_ == MAC_RECV || rx_state_ == MAC_COLL);

	/*
	 *  If the interface is in TRANSMIT mode when this packet
	 *  "arrives", then I would never have seen it and should
	 *  do a silent discard without adjusting the NAV.
	 */
	if (tx_active_) {
		Packet::free(pktRx_);
		goto done;
	}

	/*
	 * Handle collisions.
	 */
	if (rx_state_ == MAC_COLL) {
		discard(pktRx_, DROP_MAC_COLLISION);
		set_nav(usec(phymib_.getEIFS()));
		goto done;
	}

	/*
	 * Check to see if this packet was received with enough
	 * bit errors that the current level of FEC still could not
	 * fix all of the problems - ie; after FEC, the checksum still
	 * failed.
	 */
	if (ch->error() ) {
		Packet::free(pktRx_);
		set_nav(usec(phymib_.getEIFS()));
		goto done;
	}

	/*
	 * IEEE 802.11 specs, section 9.2.5.6
	 *	- update the NAV (Network Allocation Vector)
	 */
	if (dst != (u_int32_t)index_) {
		set_nav(mh->dh_duration);
	}

	/* tap out - */
	if (tap_ && type == MAC_Type_Data && MAC_Subtype_Data == subtype)
		tap_->tap(pktRx_);
	/*
	 * Adaptive Fidelity Algorithm Support - neighborhood infomation 
	 * collection
	 *
	 * Hacking: Before filter the packet, log the neighbor node
	 * I can hear the packet, the src is my neighbor
	 */
	if (netif_->node()->energy_model() && netif_->node()->energy_model()->adaptivefidelity()) {
		src = ETHER_ADDR(mh->dh_ta);
		netif_->node()->energy_model()->add_neighbor(src);
	}
	/*
	 * Address Filtering
	 */
	if (dst != (u_int32_t)index_ && dst != MAC_BROADCAST) {
		/*
		 *  We don't want to log this event, so we just free
		 *  the packet instead of calling the drop routine.
		 */
		discard(pktRx_, "---");
		goto done;
	}

	if (dst == MAC_BROADCAST && mh->dh_fc.fc_to_ds == 1 && mh->dh_fc.fc_from_ds
			== 1) {
		if (addr() != bss_id_) {
			discard(pktRx_, "---");
			goto done;
		}
		if (addr() == bss_id_ && find_client(ap_dst) == 0) {
			discard(pktRx_, "---");
			goto done;
		}
	}

	if (addr() != bss_id_ && subtype == MAC_Subtype_ProbeReq) {
		discard(pktRx_, "---");
		goto done;
	}

	switch (type) {

	case MAC_Type_Management:
		//discard(pktRx_, DROP_MAC_PACKET_ERROR);
		switch (subtype) {
		case MAC_Subtype_80211_Beacon:
			recvBEACON(pktRx_);
			break;
		case MAC_Subtype_Auth:
			recvAUTHENTICATE(pktRx_);
			break;
		case MAC_Subtype_AssocReq:
			recvASSOCREQ(pktRx_);
			break;
		case MAC_Subtype_AssocRep:
			recvASSOCREP(pktRx_);
			break;
		case MAC_Subtype_ProbeReq:
			recvPROBEREQ(pktRx_);
			break;
		case MAC_Subtype_ProbeRep:
			recvPROBEREP(pktRx_);
			break;
		default:
			fprintf(stderr, "recvTimer1:Invalid MAC Management Subtype %x\n",
					subtype);
			exit(1);
		}
		break;
	case MAC_Type_Control:
		switch (subtype) {
		case MAC_Subtype_RTS:
			recvRTS(pktRx_);
			break;
		case MAC_Subtype_CTS:
			recvCTS(pktRx_);
			break;
		case MAC_Subtype_ACK:
			recvACK(pktRx_);
			break;
		default:
			fprintf(stderr, "recvTimer2:Invalid MAC Control Subtype %x\n",
					subtype);
			exit(1);
		}
		break;
	case MAC_Type_Data:
		switch (subtype) {
		case MAC_Subtype_Data:
			recvDATA(pktRx_);
			break;
		default:
			fprintf(stderr, "recv_timer3:Invalid MAC Data Subtype %x\n",
					subtype);
			exit(1);
		}
		break;
	default:
		fprintf(stderr, "recv_timer4:Invalid MAC Type %x\n", subtype);
		exit(1);
	}
	done: pktRx_ = 0;
	rx_resume();

}

void Mac802_11::recvRTS(Packet *p) {
	struct rts_frame *rf = (struct rts_frame*)p->access(hdr_mac::offset_);

	if (tx_state_ != MAC_IDLE) {
		discard(p, DROP_MAC_BUSY);
		return;
	}

	/*
	 *  If I'm responding to someone else, discard this RTS.
	 */
	if (pktCTRL_) {
		discard(p, DROP_MAC_BUSY);
		return;
	}

	sendCTS(ETHER_ADDR(rf->rf_ta), rf->rf_duration);

	/*
	 *  Stop deferring - will be reset in tx_resume().
	 */
	if (mhDefer_.busy())
		mhDefer_.stop();

	tx_resume();

	mac_log(p);
}

/*
 * txtime()	- pluck the precomputed tx time from the packet header
 */
double Mac802_11::txtime(Packet *p) {
	struct hdr_cmn *ch = HDR_CMN(p);
	double t = ch->txtime();
	if (t < 0.0) {
		drop(p, "XXX");
		exit(1);
	}
	return t;
}

/*
 * txtime()	- calculate tx time for packet of size "psz" bytes 
 *		  at rate "drt" bps
 */
double Mac802_11::txtime(double psz, double drt) {
	double dsz = psz - phymib_.getPLCPhdrLen();
	int plcp_hdr = phymib_.getPLCPhdrLen() << 3;
	int datalen = (int)dsz << 3;
	double t = (((double)plcp_hdr)/phymib_.getPLCPDataRate())
			+ (((double)datalen)/drt);
	return (t);
}

void Mac802_11::recvCTS(Packet *p) {
	if (tx_state_ != MAC_RTS) {
		discard(p, DROP_MAC_INVALID_STATE);
		return;
	}

	assert(pktRTS_);
	Packet::free(pktRTS_);
	pktRTS_ = 0;

	assert(pktTx_);
	mhSend_.stop();

	/*
	 * The successful reception of this CTS packet implies
	 * that our RTS was successful. 
	 * According to the IEEE spec 9.2.5.3, you must 
	 * reset the ssrc_, but not the congestion window.
	 */
	ssrc_ = 0;
	tx_resume();

	mac_log(p);
}

void Mac802_11::recvDATA(Packet *p) {
	struct hdr_mac802_11 *dh = HDR_MAC802_11(p);
	// 46. QPART
	struct hdr_ip *ih = HDR_IP(p);
	// end 46
	u_int32_t dst, src, size;
	struct hdr_cmn *ch = HDR_CMN(p);

	// 47. QPART
	if (ih->fid_ > 10) {
		Qn = ih->qn_;
	}
	// end 47

	dst = ETHER_ADDR(dh->dh_ra);
	src = ETHER_ADDR(dh->dh_ta);
	size = ch->size();
	/*
	 * Adjust the MAC packet size - ie; strip
	 * off the mac header
	 */
	ch->size() -= phymib_.getHdrLen11();
	ch->num_forwards() += 1;

	/*
	 *  If we sent a CTS, clean up...
	 */
	if (dst != MAC_BROADCAST) {
		if (size >= macmib_.getRTSThreshold()) {
			if (tx_state_ == MAC_CTS) {
				assert(pktCTRL_);
				Packet::free(pktCTRL_);
				pktCTRL_ = 0;
				mhSend_.stop();
				/*
				 * Our CTS got through.
				 */
			} else {
				discard(p, DROP_MAC_BUSY);
				return;
			}
			sendACK(src);
			tx_resume();
		} else {
			/*
			 *  We did not send a CTS and there's no
			 *  room to buffer an ACK.
			 */
			if (pktCTRL_) {
				discard(p, DROP_MAC_BUSY);
				return;
			}
			sendACK(src);
			if (mhSend_.busy() == 0)
				tx_resume();
		}
	}

	/* ============================================================
	 Make/update an entry in our sequence number cache.
	 ============================================================ */

	/* Changed by Debojyoti Dutta. This upper loop of if{}else was 
	 suggested by Joerg Diederich <dieder@ibr.cs.tu-bs.de>. 
	 Changed on 19th Oct'2000 */

	if (dst != MAC_BROADCAST) {
		if (src < (u_int32_t) cache_node_count_) {
			Host *h = &cache_[src];

			if (h->seqno && h->seqno == dh->dh_scontrol) {
				discard(p, DROP_MAC_DUPLICATE);
				return;
			}
			h->seqno = dh->dh_scontrol;
		} else {
			static int count = 0;
			if (++count <= 10) {
				printf(
						"MAC_802_11: accessing MAC cache_ array out of range (src %u, dst %u, size %d)!\n",
						src, dst, cache_node_count_);
				if (count == 10)
					printf("[suppressing additional MAC cache_ warnings]\n");
			};
		};
	}

	/*
	 *  Pass the packet up to the link-layer.
	 *  XXX - we could schedule an event to account
	 *  for this processing delay.
	 */

	/* in BSS mode, if a station receives a packet via
	 * the AP, and higher layers are interested in looking
	 * at the src address, we might need to put it at
	 * the right place - lest the higher layers end up
	 * believing the AP address to be the src addr! a quick
	 * grep didn't turn up any higher layers interested in
	 * the src addr though!
	 * anyway, here if I'm the AP and the destination
	 * address (in dh_3a) isn't me, then we have to fwd
	 * the packet; we pick the real destination and set
	 * set it up for the LL; we save the real src into
	 * the dh_3a field for the 'interested in the info'
	 * receiver; we finally push the packet towards the
	 * LL to be added back to my queue - accomplish this
	 * by reversing the direction!*/

	if ((bss_id() == addr()) && ((u_int32_t)ETHER_ADDR(dh->dh_ra)!= MAC_BROADCAST) && ((u_int32_t)ETHER_ADDR(dh->dh_3a) != ((u_int32_t)addr())) && dh->dh_fc.fc_from_ds == 0) {
		struct hdr_cmn *ch = HDR_CMN(p);

		u_int32_t dst= ETHER_ADDR(dh->dh_3a);
		u_int32_t src= ETHER_ADDR(dh->dh_ta);
		/* if it is a broadcast pkt then send a copy up
		 * my stack also
		 */

		if (dst == MAC_BROADCAST) {
			uptarget_->recv(p->copy(), (Handler*) 0);
		}

		ch->next_hop() = dst;

		if (find_client(dst) == 1 || dst == MAC_BROADCAST) {
			STORE4BYTE(&src, (dh->dh_3a));
		} else {
			STORE4BYTE(&src, (dh->dh_4a));
		}

		ch->addr_type() = NS_AF_ILINK;
		ch->direction() = hdr_cmn::DOWN;

	}

	if ((bss_id() == addr()) && dh->dh_fc.fc_to_ds == 1 && dh->dh_fc.fc_from_ds
			== 1) {
		u_int32_t dst= ETHER_ADDR(dh->dh_3a);
		u_int32_t src= ETHER_ADDR(dh->dh_4a);
		if (find_client(src)) {
			update_client_table(src, 0, 0); // If the source is from another BSS and it is found in this AP's table, delete the node from the table
		}
		ch->next_hop() = dst;
		STORE4BYTE(&src, (dh->dh_3a));
		ch->addr_type() = NS_AF_ILINK;
		ch->direction() = hdr_cmn::DOWN;
	}

	uptarget_->recv(p, (Handler*) 0);

}

void Mac802_11::recvACK(Packet *p) {
	if (tx_state_ == MAC_MGMT) {
		mhSend_.stop();
		if (addr() == bss_id_) {
			if (pktASSOCREP_ && priority_queue[head] == 4) {
				Packet::free(pktASSOCREP_);
				pktASSOCREP_ = 0;
				update_client_table(associating_node_, 1, 1);
			}
			if (pktPROBEREP_ && priority_queue[head] == 1) {
				Packet::free(pktPROBEREP_);
				pktPROBEREP_ = 0;
			}
			if (pktAUTHENTICATE_ && priority_queue[head] == 3) {
				Packet::free(pktAUTHENTICATE_);
				pktAUTHENTICATE_ = 0;
				update_client_table(authenticating_node_, 1, 0);
			}
		}
		goto done;
	}
	if (tx_state_ != MAC_SEND) {
		discard(p, DROP_MAC_INVALID_STATE);
		return;
	}
	assert(pktTx_);

	mhSend_.stop();

	/*
	 * The successful reception of this ACK packet implies
	 * that our DATA transmission was successful.  Hence,
	 * we can reset the Short/Long Retry Count and the CW.
	 *
	 * need to check the size of the packet we sent that's being
	 * ACK'd, not the size of the ACK packet.
	 */
	if ((u_int32_t) HDR_CMN(pktTx_)->size() <= macmib_.getRTSThreshold())
		ssrc_ = 0;
	else
		slrc_ = 0;
	// 48. QPART
	//rst_cw();
	rst_cwBe();
	// end 48
	Packet::free(pktTx_);
	pktTx_ = 0;

	/*
	 * Backoff before sending again.
	 // 	 */

	assert(mhBackoff_.busy() == 0);
	// 49. QPART
	//mhBackoff_.start(cw_, is_idle());
	if (is_qos(p)) {
		mhBackoff_.start(cwQos_, is_idle());
		//--------------------
		//printf("cw qos dans recvACK = %d\n", cwQos_);
	} else {
		mhBackoff_.start(cwBe_, is_idle());
		//printf("cw be dans recvACK = %d\n", cwBe_);
	}
	// end 49
	done: if (addr() == bss_id_) {
		if (end() > (head + 1)) {
			shift_priority_queue();
			assert(mhBackoff_.busy() == 0);
			mhBackoff_.start(cw_, is_idle());
		} else
			priority_queue[head] = 0;
	}

	tx_resume();

	mac_log(p);
}

/* AP's association table funtions
 */
void Mac802_11::update_client_table(int num, int auth_status, int assoc_status) {
	if (client_list == NULL) {
		client_list = (struct client_table*)malloc(sizeof(struct client_table));
		client_list->client_id=num;
		client_list->auth_status=auth_status;
		client_list->assoc_status=assoc_status;
		client_list->next=NULL;
	} else {
		push(num, auth_status, assoc_status);
	}
	// 	printf("Client List for AP %d\n",index_);
	// 	struct client_table *temp;
	// 	temp = client_list;
	// 		
	// 	while (temp != NULL) {
	// 		printf("Client %d: Authenticated = %d Associated = %d\n", temp->client_id,temp->auth_status,temp->assoc_status,NOW);
	// 		temp=temp->next;
	// 	}
	// 	printf("\n");

}

void Mac802_11::push(int num, int auth_status, int assoc_status) {
	struct client_table *temp;
	temp = client_list;
	while (temp != NULL) {
		if (temp->client_id == num) {
			temp->auth_status=auth_status;
			temp->assoc_status=assoc_status;
			return;
		}
		temp=temp->next;

		if (temp == NULL) {
			break;
		}
	}

	temp = client_list;
	while (temp->next != NULL) {
		temp=temp->next;
	}
	temp->next = (struct client_table*)malloc(sizeof(struct client_table));
	temp->next->client_id = num;
	temp->next->auth_status=auth_status;
	temp->next->assoc_status=assoc_status;
	temp->next->next = NULL;
}

int Mac802_11::find_client(int num) {
	struct client_table *temp;
	temp = client_list;
	while (temp != NULL) {
		if (temp->client_id == num && temp->auth_status == 1
				&& temp->assoc_status == 1) {
			return 1;
			break;
		}

		temp=temp->next;

		if (temp == NULL) {
			return 0;
		}
	}
	return 0;
}

/* Beacon send and Receive functions
 */
void Mac802_11::sendBEACON(int src) {
	Packet *p = Packet::alloc();

	hdr_cmn* ch = HDR_CMN(p);
	struct beacon_frame *bf = (struct beacon_frame*)p->access(hdr_mac::offset_);
	double rTime;
	pktBEACON_ = 0;

	ch->uid() = 0;

	ch->ptype() = PT_MAC;
	ch->size() = phymib_.getBEACONlen();
	ch->iface() = -2;
	ch->error() = 0;

	bzero(bf, MAC_HDR_LEN);

	/* Note: I had to give a different name for MAC_Subtype_80211_Beacon as MAC_Subtype_80211_Beacon as MAC_Subtype_80211_Beacon is already defined for 802.15.4 with a different value!! (See cmu-trace.cc).
	 */

	bf->bf_fc.fc_protocol_version = MAC_ProtocolVersion;
	bf->bf_fc.fc_type = MAC_Type_Management;
	bf->bf_fc.fc_subtype = MAC_Subtype_80211_Beacon;
	bf->bf_fc.fc_to_ds = 0;
	bf->bf_fc.fc_from_ds = 0;
	bf->bf_fc.fc_more_frag = 0;
	bf->bf_fc.fc_retry = 0;
	bf->bf_fc.fc_pwr_mgt = 0;
	bf->bf_fc.fc_more_data = 0;
	bf->bf_fc.fc_wep = 0;
	bf->bf_fc.fc_order = 0;

	int dst= MAC_BROADCAST;
	STORE4BYTE(&dst, (bf->bf_ra));
	STORE4BYTE(&src, (bf->bf_ta));
	STORE4BYTE(&ap_addr, (bf->bf_3a));

	bf->bf_timestamp = Scheduler::instance().clock();
	bf->bf_bcninterval = phymib_.getBeaconInterval();

	/* store beacon tx time */

	ch->txtime() = txtime(ch->size(), basicRate_);

	/* calculate beacon duration??? */
	bf->bf_duration = 0;

	pktBEACON_ = p;

	BeaconTxtime_ = txtime(phymib_.getBEACONlen(), basicRate_);

	if (mhBackoff_.busy() == 0) {
		if (is_idle()) {
			if (mhDefer_.busy() == 0) {

				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
					priority_queue[head] = 2;
				} else {
					rTime = (Random::random() % cw_) * (phymib_.getSlotTime());
					mhDefer_.start(phymib_.getDIFS() + rTime);
				}
			}
		} else {
			/*
			 * If the medium is NOT IDLE, then we start
			 * the backoff timer.
			 */

			mhBackoff_.start(cw_, is_idle());
			priority_queue[head] = 2;
		}
	} else {
		priority_queue[end()] = 2;
	}

}

int Mac802_11::check_pktBEACON() {
	struct beacon_frame *bf =
			(struct beacon_frame*)pktBEACON_->access(hdr_mac::offset_);
	bf->bf_timestamp = Scheduler::instance().clock();

	struct hdr_mac802_11 *mh;
	double timeout;

	assert(mhBackoff_.busy() == 0);

	if (pktBEACON_ == 0)
		return -1;
	mh = HDR_MAC802_11(pktBEACON_);

	switch (mh->dh_fc.fc_subtype) {
	case MAC_Subtype_80211_Beacon:
		if (!is_idle()) {
			inc_cw();
			mhBackoff_.start(cw_, is_idle());
			return 0;
		}
		// 50. QPART
		//setTxState(MAC_BCN);
		setTxState(MAC_BCN, pktBEACON_);
		// end 50
		timeout = txtime(phymib_.getBEACONlen(), basicRate_);
		break;
	default:
		fprintf(stderr, "check_pktBEACON:Invalid MAC Control subtype\n");
		exit(1);
	}
	transmit(pktBEACON_, timeout);

	return 0;
}

void Mac802_11::recvBEACON(Packet *p) {
	struct beacon_frame *bf = (struct beacon_frame*)p->access(hdr_mac::offset_);

	if (tx_state_ != MAC_IDLE) {
		discard(p, DROP_MAC_BUSY);
		return;
	}
	u_int32_t bss_id, src;

	//double timestamp, beaconint;
	bss_id = ETHER_ADDR(bf->bf_3a);
	src = ETHER_ADDR(bf->bf_ta);
	infra_mode_ = 1;
	//timestamp = bf->bf_timestamp;
	Pr = p->txinfo_.RxPr;
	if (addr() != ap_addr && ScanType_ == PASSIVE) {
		if (authenticated == 0 && associated == 0) {
			if (find_ap(src, Pr) != 1) {
				update_ap_table(src, Pr);
			}
		}
	}

	mac_log(p);
}

void Mac802_11::passive_scan() {
	if (addr() != ap_addr && ScanType_ == PASSIVE) {
		if (authenticated == 0 && associated == 0) {
			ap_temp = strongest_ap();
			if (!pktAUTHENTICATE_)
				sendAUTHENTICATE(ap_temp);
		}

	}
}
void Mac802_11::active_scan() {

	if (addr() != ap_addr && ScanType_ == ACTIVE) {
		if (authenticated == 0 && associated == 0) {
			ap_temp = strongest_ap();
			sendAUTHENTICATE(ap_temp);
		}

	}
}

// Association functions

void Mac802_11::sendASSOCREQ(int dst) {
	Packet *p = Packet::alloc();
	hdr_cmn* ch = HDR_CMN(p);
	struct assocreq_frame *acrqf =
			(struct assocreq_frame*)p->access(hdr_mac::offset_);

	double rTime;
	pktASSOCREQ_ = 0;

	ch->uid() = 0;

	ch->ptype() = PT_MAC;
	ch->size() = phymib_.getASSOCREQlen();
	ch->iface() = -2;
	ch->error() = 0;

	bzero(acrqf, MAC_HDR_LEN);

	acrqf->acrqf_fc.fc_protocol_version = MAC_ProtocolVersion;
	acrqf->acrqf_fc.fc_type = MAC_Type_Management;
	acrqf->acrqf_fc.fc_subtype = MAC_Subtype_AssocReq;
	acrqf->acrqf_fc.fc_to_ds = 0;
	acrqf->acrqf_fc.fc_from_ds = 0;
	acrqf->acrqf_fc.fc_more_frag= 0;
	acrqf->acrqf_fc.fc_retry = 0;
	acrqf->acrqf_fc.fc_pwr_mgt = 0;
	acrqf->acrqf_fc.fc_more_data= 0;
	acrqf->acrqf_fc.fc_wep = 0;
	acrqf->acrqf_fc.fc_order = 0;

	STORE4BYTE(&dst, (acrqf->acrqf_ra));
	STORE4BYTE(&index_, (acrqf->acrqf_ta));
	STORE4BYTE(&dst, (acrqf->acrqf_3a));

	ch->txtime() = txtime(ch->size(), basicRate_);
	acrqf->acrqf_duration = 0;

	pktASSOCREQ_ = p;

	if (mhBackoff_.busy() == 0) {
		if (is_idle()) {
			if (mhDefer_.busy() == 0) {
				/*
				 * If we are already deferring, there is no
				 * need to reset the Defer timer.
				 */
				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
				} else {
					rTime = (Random::random() % cw_) * (phymib_.getSlotTime());
					mhDefer_.start(phymib_.getDIFS() + rTime);
				}
			}
		} else {
			/*
			 * If the medium is NOT IDLE, then we start
			 * the backoff timer.
			 */
			mhBackoff_.start(cw_, is_idle());
		}
	}
}

int Mac802_11::check_pktASSOCREQ() {
	struct hdr_mac802_11 *mh;
	double timeout;

	assert(mhBackoff_.busy() == 0);

	if (pktASSOCREQ_ == 0)
		return -1;
	mh = HDR_MAC802_11(pktASSOCREQ_);

	switch (mh->dh_fc.fc_subtype) {
	case MAC_Subtype_AssocReq:
		if (!is_idle()) {
			inc_cw();
			mhBackoff_.start(cw_, is_idle());
			return 0;
		}
		// 51. QPART
		//setTxState(MAC_MGMT);
		setTxState(MAC_MGMT, pktASSOCREQ_);
		// end 51
		timeout = txtime(phymib_.getASSOCREQlen(), basicRate_)
				+ DSSS_MaxPropagationDelay + macmib_.getMaxChannelTime()
				+ txtime(phymib_.getASSOCREPlen(), basicRate_)
				+ DSSS_MaxPropagationDelay;
		break;
	default:
		fprintf(stderr, "check_pktASSOCREQ:Invalid MAC Control subtype\n");
		exit(1);
	}
	transmit(pktASSOCREQ_, timeout);

	return 0;
}

void Mac802_11::sendASSOCREP(int dst) {
	Packet *p = Packet::alloc();
	hdr_cmn* ch = HDR_CMN(p);
	struct assocrep_frame *acrpf =
			(struct assocrep_frame*)p->access(hdr_mac::offset_);
	double rTime;
	pktASSOCREP_ = 0;

	ch->uid() = 0;

	ch->ptype() = PT_MAC;
	ch->size() = phymib_.getASSOCREPlen();
	ch->iface() = -2;
	ch->error() = 0;

	bzero(acrpf, MAC_HDR_LEN);

	acrpf->acrpf_fc.fc_protocol_version = MAC_ProtocolVersion;
	acrpf->acrpf_fc.fc_type = MAC_Type_Management;
	acrpf->acrpf_fc.fc_subtype = MAC_Subtype_AssocRep;
	acrpf->acrpf_fc.fc_to_ds = 0;
	acrpf->acrpf_fc.fc_from_ds = 0;
	acrpf->acrpf_fc.fc_more_frag= 0;
	acrpf->acrpf_fc.fc_retry = 0;
	acrpf->acrpf_fc.fc_pwr_mgt = 0;
	acrpf->acrpf_fc.fc_more_data= 0;
	acrpf->acrpf_fc.fc_wep = 0;
	acrpf->acrpf_fc.fc_order = 0;

	STORE4BYTE(&dst, (acrpf->acrpf_ra));
	STORE4BYTE(&index_, (acrpf->acrpf_ta));
	STORE4BYTE(&index_, (acrpf->acrpf_3a));

	acrpf->acrpf_statuscode = 0;
	ch->txtime() = txtime(ch->size(), basicRate_);
	acrpf->acrpf_duration = 0;

	pktASSOCREP_ = p;

	if (mhBackoff_.busy() == 0) {
		if (is_idle()) {
			if (mhDefer_.busy() == 0) {
				/*
				 * If we are already deferring, there is no
				 * need to reset the Defer timer.
				 */
				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
					priority_queue[head] = 4;
				} else {
					rTime = (Random::random() % cw_) * (phymib_.getSlotTime());
					mhDefer_.start(phymib_.getDIFS() + rTime);
				}
			}
		} else {
			/*
			 * If the medium is NOT IDLE, then we start
			 * the backoff timer.
			 */
			mhBackoff_.start(cw_, is_idle());
			priority_queue[head] = 4;

		}

	} else {
		priority_queue[end()] = 4;
	}

}

int Mac802_11::check_pktASSOCREP() {
	struct hdr_mac802_11 *mh;
	double timeout;

	assert(mhBackoff_.busy() == 0);
	if (pktASSOCREP_ == 0)
		return -1;
	mh = HDR_MAC802_11(pktASSOCREP_);
	switch (mh->dh_fc.fc_subtype) {
	case MAC_Subtype_AssocRep:
		if (!is_idle()) {
			inc_cw();
			mhBackoff_.start(cw_, is_idle());
			return 0;
		}

		// 52. QPART
		setTxState(MAC_MGMT, pktASSOCREP_);
		// end 53
		
		timeout = txtime(phymib_.getASSOCREPlen(), basicRate_)
				+ DSSS_MaxPropagationDelay + phymib_.getSIFS() + txtime(
				phymib_.getACKlen(), basicRate_) + DSSS_MaxPropagationDelay;

		break;
	default:
		fprintf(stderr, "check_pktASSOCREP:Invalid MAC Control subtype\n");
		exit(1);
	}
	transmit(pktASSOCREP_, timeout);

	return 0;
}

void Mac802_11::recvASSOCREQ(Packet *p) {
	struct assocreq_frame *acrqf =
			(struct assocreq_frame*)p->access(hdr_mac::offset_);

	if (tx_state_ != MAC_IDLE) {
		discard(p, DROP_MAC_BUSY);
		return;
	}
	u_int32_t bss_id, src;

	bss_id = ETHER_ADDR(acrqf->acrqf_3a);
	src = ETHER_ADDR(acrqf->acrqf_ta);

	if (!pktASSOCREP_) {
		sendASSOCREP(src);
		associating_node_ = src;
	} else {
		discard(p, DROP_MAC_BUSY);
		return;
	}
	tx_resume();

	mac_log(p);
}

void Mac802_11::recvASSOCREP(Packet *p) {
	struct assocrep_frame *acrpf =
			(struct assocrep_frame*)p->access(hdr_mac::offset_);

	assert(pktASSOCREQ_);
	Packet::free(pktASSOCREQ_);
	pktASSOCREQ_ = 0;
	mhSend_.stop();

	u_int32_t src;
	u_int16_t statuscode;

	src = ETHER_ADDR(acrpf->acrpf_ta);
	statuscode = acrpf->acrpf_statuscode;

	if (statuscode == 0) {
		associated = 1;
		deletelist();
		if (handoff) {
			handoff = 0; //handoff completed
		}
		sendACK(src);

	}
	if (mhSend_.busy() == 0)
		tx_resume();

	mac_log(p);

}

//Authentication functions

void Mac802_11::sendAUTHENTICATE(int dst) {
	Packet *p = Packet::alloc();
	hdr_cmn* ch = HDR_CMN(p);
	struct auth_frame *authf =(struct auth_frame*)p->access(hdr_mac::offset_);

	double rTime;
	pktAUTHENTICATE_ = 0;

	ch->uid() = 0;

	ch->ptype() = PT_MAC;
	ch->size() = phymib_.getAUTHENTICATElen();
	ch->iface() = -2;
	ch->error() = 0;

	bzero(authf, MAC_HDR_LEN);

	authf->authf_fc.fc_protocol_version = MAC_ProtocolVersion;
	authf->authf_fc.fc_type = MAC_Type_Management;
	authf->authf_fc.fc_subtype = MAC_Subtype_Auth;
	authf->authf_fc.fc_to_ds = 0;
	authf->authf_fc.fc_from_ds = 0;
	authf->authf_fc.fc_more_frag= 0;
	authf->authf_fc.fc_retry = 0;
	authf->authf_fc.fc_pwr_mgt = 0;
	authf->authf_fc.fc_more_data= 0;
	authf->authf_fc.fc_wep = 0;
	authf->authf_fc.fc_order = 0;

	STORE4BYTE(&dst, (authf->authf_ra));
	STORE4BYTE(&index_, (authf->authf_ta));
	if (addr() != bss_id_)
		STORE4BYTE(&dst, (authf->authf_3a));
	else
		STORE4BYTE(&index_, (authf->authf_3a));
	authf->authf_algono = 0; //Open system authentication

	if (addr() != bss_id_) {
		authf->authf_seqno = 1; // 
	} else {
		authf->authf_seqno = 2; //
		authf->authf_statuscode = 0;
	}

	ch->txtime() = txtime(ch->size(), basicRate_);
	if (addr() == bss_id_) {
		authf->authf_duration = usec(txtime(phymib_.getACKlen(), basicRate_)
				+ phymib_.getSIFS());
	} else {
		authf->authf_duration = 0;
	}

	pktAUTHENTICATE_ = p;

	if (mhBackoff_.busy() == 0) {
		if (is_idle()) {
			if (mhDefer_.busy() == 0) {
				/*
				 * If we are already deferring, there is no
				 * need to reset the Defer timer.
				 */
				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
					priority_queue[head] = 3;
				} else {
					rTime = (Random::random() % cw_) * (phymib_.getSlotTime());
					mhDefer_.start(phymib_.getDIFS() + rTime);
				}
			}
		} else {
			/*
			 * If the medium is NOT IDLE, then we start
			 * the backoff timer.
			 */
			mhBackoff_.start(cw_, is_idle());
			priority_queue[head] = 3;

		}
	} else {
		priority_queue[end()] = 3;
	}

}

int Mac802_11::check_pktAUTHENTICATE() {
	struct hdr_mac802_11 *mh;
	double timeout;

	assert(mhBackoff_.busy() == 0);

	if (pktAUTHENTICATE_ == 0)
		return -1;
	mh = HDR_MAC802_11(pktAUTHENTICATE_);

	switch (mh->dh_fc.fc_subtype) {
	case MAC_Subtype_Auth:
		if (!is_idle()) {
			inc_cw();
			mhBackoff_.start(cw_, is_idle());
			return 0;
		}
		// 54. QPART
		setTxState(MAC_MGMT, pktAUTHENTICATE_);
		// end 54
		if (addr() != bss_id_) {
			timeout = txtime(phymib_.getAUTHENTICATElen(), basicRate_)
					+ DSSS_MaxPropagationDelay // XXX
					+ macmib_.getMaxChannelTime() + txtime(
					phymib_.getAUTHENTICATElen(), basicRate_)
					+ DSSS_MaxPropagationDelay;
		} else {
			timeout = txtime(phymib_.getAUTHENTICATElen(), basicRate_)
					+ DSSS_MaxPropagationDelay // XXX
					+ phymib_.getSIFS() + txtime(phymib_.getACKlen(),
					basicRate_) + DSSS_MaxPropagationDelay;
		}
		break;
	default:
		fprintf(stderr, "check_pktAUTHENTICATE:Invalid MAC Control subtype\n");
		exit(1);
	}

	transmit(pktAUTHENTICATE_, timeout);

	return 0;
}

void Mac802_11::recvAUTHENTICATE(Packet *p) {
	struct auth_frame *authf = (struct auth_frame*)p->access(hdr_mac::offset_);

	if (addr() != bss_id_) {
		assert(pktAUTHENTICATE_);
		Packet::free(pktAUTHENTICATE_);
		pktAUTHENTICATE_ = 0;
		mhSend_.stop();
	} else {
		if (tx_state_ != MAC_IDLE) {
			discard(p, DROP_MAC_BUSY);
			return;
		}
	}

	u_int32_t src;

	src = ETHER_ADDR(authf->authf_ta);

	if (addr() == ap_addr) {
		if (authf->authf_seqno == 1) {
			if (!pktAUTHENTICATE_) {// AP is not currently involved in Authentication with any other STA 
				sendAUTHENTICATE(src);
				authenticating_node_ = src;
			} else {
				discard(p, DROP_MAC_BUSY);
				return;
			}
		} else
			printf("Out of sequence\n");
	} else if (authf->authf_seqno == 2 && authf->authf_statuscode == 0) {
		authenticated = 1;
		if (bss_id_ != ETHER_ADDR(authf->authf_3a) && handoff == 1) {
			printf("Client %d: Handoff from AP %d to AP %d\n", index_, bss_id_,
					ETHER_ADDR(authf->authf_3a));
		}
		bss_id_ = ETHER_ADDR(authf->authf_3a);
		sendACK(src);
		mhProbe_.start(phymib_.getSIFS() + txtime(phymib_.getACKlen(),
				basicRate_) + macmib_.getMaxChannelTime());

	}

	if (mhSend_.busy() == 0)
		tx_resume();

	mac_log(p);

}

// Active Scanning Functions 
void Mac802_11::sendPROBEREQ(int dst) {
	Packet *p = Packet::alloc();
	hdr_cmn* ch = HDR_CMN(p);
	struct probereq_frame *prrqf =
			(struct probereq_frame*)p->access(hdr_mac::offset_);

	double rTime;
	pktPROBEREQ_ = 0;

	ch->uid() = 0;

	ch->ptype() = PT_MAC;
	ch->size() = phymib_.getPROBEREQlen();
	ch->iface() = -2;
	ch->error() = 0;

	bzero(prrqf, MAC_HDR_LEN);

	prrqf->prrqf_fc.fc_protocol_version = MAC_ProtocolVersion;
	prrqf->prrqf_fc.fc_type = MAC_Type_Management;
	prrqf->prrqf_fc.fc_subtype = MAC_Subtype_ProbeReq;
	prrqf->prrqf_fc.fc_to_ds = 0;
	prrqf->prrqf_fc.fc_from_ds = 0;
	prrqf->prrqf_fc.fc_more_frag= 0;
	prrqf->prrqf_fc.fc_retry = 0;
	prrqf->prrqf_fc.fc_pwr_mgt = 0;
	prrqf->prrqf_fc.fc_more_data= 0;
	prrqf->prrqf_fc.fc_wep = 0;
	prrqf->prrqf_fc.fc_order = 0;

	STORE4BYTE(&dst, (prrqf->prrqf_ra));
	STORE4BYTE(&index_, (prrqf->prrqf_ta));
	STORE4BYTE(&dst, (prrqf->prrqf_3a));

	ch->txtime() = txtime(ch->size(), basicRate_);
	prrqf->prrqf_duration = 0;

	pktPROBEREQ_ = p;

	if (mhBackoff_.busy() == 0) {
		if (is_idle()) {
			if (mhDefer_.busy() == 0) {
				/*
				 * If we are already deferring, there is no
				 * need to reset the Defer timer.
				 */
				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
				} else {
					rTime = (Random::random() % cw_) * (phymib_.getSlotTime());
					mhDefer_.start(phymib_.getDIFS() + rTime);
				}
			}
		} else {
			/*
			 * If the medium is NOT IDLE, then we start
			 * the backoff timer.
			 */
			mhBackoff_.start(cw_, is_idle());

		}
	}
}

int Mac802_11::check_pktPROBEREQ() {
	struct hdr_mac802_11 *mh;
	double timeout;

	assert(mhBackoff_.busy() == 0);

	if (pktPROBEREQ_ == 0)
		return -1;
	mh = HDR_MAC802_11(pktPROBEREQ_);

	switch (mh->dh_fc.fc_subtype) {
	case MAC_Subtype_ProbeReq:
		if (!is_idle()) {
			inc_cw();
			mhBackoff_.start(cw_, is_idle());
			return 0;
		}
		// 55. QPART
		setTxState(MAC_MGMT, pktPROBEREQ_);
		// end 55
		timeout = txtime(phymib_.getPROBEREQlen(), basicRate_)
				+ DSSS_MaxPropagationDelay; // XXX
		break;
	default:
		fprintf(stderr, "check_pktPROBEREQ:Invalid MAC Control subtype\n");
		exit(1);
	}
	transmit(pktPROBEREQ_, timeout);
	mhProbe_.start(macmib_.getMinChannelTime());
	OnMinChannelTime = 1;
	return 0;
}

void Mac802_11::sendPROBEREP(int dst) {
	Packet *p = Packet::alloc();

	hdr_cmn* ch = HDR_CMN(p);
	struct proberep_frame *prrpf =
			(struct proberep_frame*)p->access(hdr_mac::offset_);

	pktPROBEREP_ = 0;

	ch->uid() = 0;

	double rTime;

	ch->ptype() = PT_MAC;
	ch->size() = phymib_.getPROBEREPlen();
	ch->iface() = -2;
	ch->error() = 0;

	bzero(prrpf, MAC_HDR_LEN);

	prrpf->prrpf_fc.fc_protocol_version = MAC_ProtocolVersion;
	prrpf->prrpf_fc.fc_type = MAC_Type_Management;
	prrpf->prrpf_fc.fc_subtype = MAC_Subtype_ProbeRep;
	prrpf->prrpf_fc.fc_to_ds = 0;
	prrpf->prrpf_fc.fc_from_ds = 0;
	prrpf->prrpf_fc.fc_more_frag= 0;
	prrpf->prrpf_fc.fc_retry = 0;
	prrpf->prrpf_fc.fc_pwr_mgt = 0;
	prrpf->prrpf_fc.fc_more_data= 0;
	prrpf->prrpf_fc.fc_wep = 0;
	prrpf->prrpf_fc.fc_order = 0;

	STORE4BYTE(&dst, (prrpf->prrpf_ra));
	STORE4BYTE(&index_, (prrpf->prrpf_ta));
	STORE4BYTE(&index_, (prrpf->prrpf_3a));

	//	prrpf->prrpf_timestamp = Scheduler::instance().clock();
	prrpf->prrpf_bcninterval = phymib_.getBeaconInterval();

	ch->txtime() = txtime(ch->size(), basicRate_);
	prrpf->prrpf_duration = 0;

	pktPROBEREP_ = p;

	if (mhBackoff_.busy() == 0) {
		if (is_idle()) {
			if (mhDefer_.busy() == 0) {
				/*
				 * If we are already deferring, there is no
				 * need to reset the Defer timer.
				 */
				if (bugFix_timer_) {
					mhBackoff_.start(cw_, is_idle(), phymib_.getDIFS());
					priority_queue[head] = 1;
				} else {
					rTime = (Random::random() % cw_) * (phymib_.getSlotTime());
					mhDefer_.start(phymib_.getDIFS() + rTime);
				}
			}
		} else {
			/*
			 * If the medium is NOT IDLE, then we start
			 * the backoff timer.
			 */
			mhBackoff_.start(cw_, is_idle());
			priority_queue[head] = 1;

		}

	} else {
		priority_queue[end()] = 1;
	}

}

int Mac802_11::check_pktPROBEREP() {
	struct proberep_frame *prrpf =
			(struct proberep_frame*)pktPROBEREP_->access(hdr_mac::offset_);
	prrpf->prrpf_timestamp = Scheduler::instance().clock();

	struct hdr_mac802_11 *mh;
	double timeout;

	assert(mhBackoff_.busy() == 0);

	if (pktPROBEREP_ == 0)
		return -1;
	mh = HDR_MAC802_11(pktPROBEREP_);

	switch (mh->dh_fc.fc_subtype) {
	case MAC_Subtype_ProbeRep:
		if (!is_idle()) {
			inc_cw();
			mhBackoff_.start(cw_, is_idle());
			return 0;
		}
		// 56. QPART
		setTxState(MAC_MGMT, pktPROBEREP_);
		// end 56
		timeout = txtime(phymib_.getPROBEREPlen(), basicRate_)
				+ DSSS_MaxPropagationDelay // XXX
				+ phymib_.getSIFS() + txtime(phymib_.getACKlen(), basicRate_)
				+ DSSS_MaxPropagationDelay;
		break;
	default:
		fprintf(stderr, "check_pktPROBEREP:Invalid MAC Control subtype\n");
		exit(1);
	}
	transmit(pktPROBEREP_, timeout);

	return 0;
}

void Mac802_11::recvPROBEREQ(Packet *p) {
	struct probereq_frame *prrqf =
			(struct probereq_frame*)p->access(hdr_mac::offset_);

	if (tx_state_ != MAC_IDLE) {
		discard(p, DROP_MAC_BUSY);
		return;
	}
	u_int32_t bss_id, src;
	bss_id = ETHER_ADDR(prrqf->prrqf_3a);
	src = ETHER_ADDR(prrqf->prrqf_ta);

	if (!pktPROBEREP_) {
		sendPROBEREP(src);
	} else {
		discard(p, DROP_MAC_BUSY);
		return;
	}

	tx_resume();

	mac_log(p);
}

void Mac802_11::recvPROBEREP(Packet *p) {
	struct proberep_frame *prrpf =
			(struct proberep_frame*)p->access(hdr_mac::offset_);

	u_int32_t bss_id, src;

	Pr = p->txinfo_.RxPr;
	src = ETHER_ADDR(prrpf->prrpf_ta);
	bss_id = ETHER_ADDR(prrpf->prrpf_ta);

	update_ap_table(src, Pr);

	sendACK(src);

	if (mhSend_.busy() == 0)
		tx_resume();

	mac_log(p);

}

void Mac802_11::checkAssocAuthStatus() {
	if (addr() != bss_id_) {
		if (authenticated == 0 && associated == 0) {

			sendAUTHENTICATE(strongest_ap());
		}
		if (authenticated == 1 && associated == 0) {
			sendASSOCREQ(bss_id_);
		}
	}
}

/* STA's beacon power table funtions
 */
void Mac802_11::update_ap_table(int num, double power) {
	if (ap_list == NULL) {
		ap_list = (struct ap_table*)malloc(sizeof(struct ap_table));
		ap_list->ap_id=num;
		ap_list->ap_power = power;
		ap_list->next=NULL;
	} else {
		push_ap(num, power);
	}
	struct ap_table *temp;
	temp = ap_list;
	// 	while (temp != NULL) {
	// 		printf("Client %d: AP %d and %f\t", index_, temp->ap_id,temp->ap_power);
	// 		temp=temp->next;
	// 	}
	// 	printf("\n");
}

void Mac802_11::push_ap(int num, double power) {
	struct ap_table *temp;
	temp = ap_list;
	while (temp->next != NULL) {
		temp=temp->next;
	}
	temp->next = (struct ap_table*)malloc(sizeof(struct ap_table));
	temp->next->ap_id = num;
	temp->next->ap_power= power;
	temp->next->next = NULL;
}

void Mac802_11::deletelist() {
	struct ap_table *temp;
	while (ap_list != NULL) {

		temp = ap_list;
		ap_list = ap_list->next;
		free(temp);
	}

}

int Mac802_11::strongest_ap() {
	struct ap_table *temp;
	double max_power;
	int ap;
	temp = ap_list;
	if (ap_list == NULL)
		return -1;
	max_power = 0;
	while (temp != NULL) {
		if (temp->ap_power > max_power) {
			max_power = temp->ap_power;
			ap = temp->ap_id;
		}
		temp = temp->next;
	}

	return ap;
}

int Mac802_11::find_ap(int num, double power) {
	struct ap_table *temp;
	temp = ap_list;
	while (temp != NULL) {
		if (temp->ap_id == num && temp->ap_power == power) {
			return 1;
		}

		temp=temp->next;

		if (temp == NULL) {
			return 0;
		}
	}
	return 0;
}

int Mac802_11::end() {
	int end;
	end = head;
	while (priority_queue[end] != 0) {
		end = end + 1;
	}
	return end;
}

void Mac802_11::shift_priority_queue() {
	int i;
	i = head;
	while (priority_queue[i] != 0) {
		priority_queue[i] = priority_queue[i+1];
		i = i + 1;
	}
}
